/* 1 if the next opcode is to be specially indented. */
int sparc_indent_opcode = 0;
+static bool sparc_handle_option (size_t, const char *, int);
static void sparc_init_modes (void);
static void scan_record_type (tree, int *, int *, int *);
static int function_arg_slotno (const CUMULATIVE_ARGS *, enum machine_mode,
static int epilogue_renumber (rtx *, int);
static bool sparc_assemble_integer (rtx, unsigned int, int);
static int set_extends (rtx);
-static void load_pic_register (void);
+static void emit_pic_helper (void);
+static void load_pic_register (bool);
static int save_or_restore_regs (int, int, rtx, int, int);
-static void emit_save_regs (void);
-static void emit_restore_regs (void);
+static void emit_save_or_restore_regs (int);
static void sparc_asm_function_prologue (FILE *, HOST_WIDE_INT);
static void sparc_asm_function_epilogue (FILE *, HOST_WIDE_INT);
#ifdef OBJECT_FORMAT_ELF
static int sparc_arg_partial_bytes (CUMULATIVE_ARGS *,
enum machine_mode, tree, bool);
static void sparc_dwarf_handle_frame_unspec (const char *, rtx, int);
+static void sparc_file_end (void);
#ifdef SUBTARGET_ATTRIBUTE_TABLE
const struct attribute_spec sparc_attribute_table[];
#endif
/* Code model option as passed by user. */
const char *sparc_cmodel_string;
+
/* Parsed value. */
enum cmodel sparc_cmodel;
/* CPU type. This is set from TARGET_CPU_DEFAULT and -m{cpu,tune}=xxx. */
enum processor_type sparc_cpu;
-\f
+
+/* Whether\fan FPU option was specified. */
+static bool fpu_option_set = false;
+
/* Initialize the GCC target structure. */
/* The sparc default is to use .half rather than .short for aligned
#undef TARGET_RELAXED_ORDERING
#define TARGET_RELAXED_ORDERING SPARC_RELAXED_ORDERING
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION sparc_handle_option
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END sparc_file_end
+
struct gcc_target targetm = TARGET_INITIALIZER;
-\f
+
+/* Implement TARGET_HANDLE_OPTION. */
+
+static bool
+sparc_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case OPT_mfpu:
+ case OPT_mhard_float:
+ case OPT_msoft_float:
+ fpu_option_set = true;
+ break;
+
+ case OPT_mcpu_:
+ sparc_select[1].string = arg;
+ break;
+
+ case OPT_mtune_:
+ sparc_select[2].string = arg;
+ break;
+
+ case OPT_mcmodel_:
+ sparc_cmodel_string = arg;
+ break;
+ }
+
+ return true;
+}
+
/* Validate and override various options, and do some machine dependent
initialization. */
for (def = &cpu_default[0]; def->name; ++def)
if (def->cpu == TARGET_CPU_DEFAULT)
break;
- if (! def->name)
- abort ();
+ gcc_assert (def->name);
sparc_select[0].string = def->name;
for (sel = &sparc_select[0]; sel->name; ++sel)
}
/* If -mfpu or -mno-fpu was explicitly used, don't override with
- the processor default. Clear MASK_FPU_SET to avoid confusing
- the reverse mapping from switch values to names. */
- if (TARGET_FPU_SET)
- {
- target_flags = (target_flags & ~MASK_FPU) | fpu;
- target_flags &= ~MASK_FPU_SET;
- }
+ the processor default. */
+ if (fpu_option_set)
+ target_flags = (target_flags & ~MASK_FPU) | fpu;
/* Don't allow -mvis if FPU is disabled. */
if (! TARGET_FPU)
v9_regcmp_p (enum rtx_code code)
{
return (code == EQ || code == NE || code == GE || code == LT
- || code == LE || code == GT);
-}
-
-\f
-/* 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. */
-
-int
-fp_sethi_p (rtx op)
-{
- if (GET_CODE (op) == CONST_DOUBLE)
- {
- REAL_VALUE_TYPE r;
- long i;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- if (REAL_VALUES_EQUAL (r, dconst0) &&
- ! REAL_VALUE_MINUS_ZERO (r))
- return 0;
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- if (SPARC_SETHI_P (i))
- return 1;
- }
-
- return 0;
-}
-
-/* Nonzero if OP is a floating point constant which can
- be loaded into an integer register using a single
- mov instruction. */
-
-int
-fp_mov_p (rtx op)
-{
- if (GET_CODE (op) == CONST_DOUBLE)
- {
- REAL_VALUE_TYPE r;
- long i;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- if (REAL_VALUES_EQUAL (r, dconst0) &&
- ! REAL_VALUE_MINUS_ZERO (r))
- return 0;
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- if (SPARC_SIMM13_P (i))
- return 1;
- }
-
- return 0;
-}
-
-/* Nonzero if OP is a floating point constant which can
- be loaded into an integer register using a high/losum
- instruction sequence. */
-
-int
-fp_high_losum_p (rtx op)
-{
- /* The constraints calling this should only be in
- SFmode move insns, so any constant which cannot
- be moved using a single insn will do. */
- if (GET_CODE (op) == CONST_DOUBLE)
- {
- REAL_VALUE_TYPE r;
- long i;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- if (REAL_VALUES_EQUAL (r, dconst0) &&
- ! REAL_VALUE_MINUS_ZERO (r))
- return 0;
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- if (! SPARC_SETHI_P (i)
- && ! SPARC_SIMM13_P (i))
- return 1;
- }
-
- 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)
-{
- if (GET_CODE (op) != MEM)
- abort ();
- 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. */
-
-int
-tls_symbolic_operand (rtx op)
-{
- if (GET_CODE (op) != SYMBOL_REF)
- 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);
-}
-\f
-/* 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))));
+ || code == LE || code == GT);
}
-/* 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. */
+/* Nonzero if OP is a floating point constant which can
+ be loaded into an integer register using a single
+ sethi instruction. */
int
-arith11_operand (rtx op, enum machine_mode mode)
+fp_sethi_p (rtx op)
{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && SPARC_SIMM11_P (INTVAL (op))));
-}
+ if (GET_CODE (op) == CONST_DOUBLE)
+ {
+ REAL_VALUE_TYPE r;
+ long i;
-/* 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. */
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ return !SPARC_SIMM13_P (i) && SPARC_SETHI_P (i);
+ }
-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 0;
}
-/* 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. */
+/* Nonzero if OP is a floating point constant which can
+ be loaded into an integer register using a single
+ mov instruction. */
int
-arith_double_operand (rtx op, enum machine_mode mode)
+fp_mov_p (rtx op)
{
- 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))));
-}
+ if (GET_CODE (op) == CONST_DOUBLE)
+ {
+ REAL_VALUE_TYPE r;
+ long i;
-/* Return true if OP is a constant 4096 for DImode on ARCH64 */
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ return SPARC_SIMM13_P (i);
+ }
-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 0;
}
-/* Return true if OP is suitable as second operand for add/sub in DImode */
+/* Nonzero if OP is a floating point constant which can
+ be loaded into an integer register using a high/losum
+ instruction sequence. */
int
-arith_double_add_operand (rtx op, enum machine_mode mode)
+fp_high_losum_p (rtx op)
{
- 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? */
+ /* The constraints calling this should only be in
+ SFmode move insns, so any constant which cannot
+ be moved using a single insn will do. */
+ if (GET_CODE (op) == CONST_DOUBLE)
+ {
+ REAL_VALUE_TYPE r;
+ long i;
-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? */
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ return !SPARC_SIMM13_P (i) && !SPARC_SETHI_P (i);
+ }
-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 0;
}
-/* 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. */
+/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
+ otherwise return 0. */
int
-small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+tls_symbolic_operand (rtx op)
{
- return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+ return SYMBOL_REF_TLS_MODEL (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))));
-}
+/* Expand a move instruction. Return true if all work is done. */
-/* 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. */
+bool
+sparc_expand_move (enum machine_mode mode, rtx *operands)
+{
+ /* Handle sets of MEM first. */
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ /* 0 is a register (or a pair of registers) on SPARC. */
+ if (register_or_zero_operand (operands[1], mode))
+ return false;
-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
-}
+ if (!reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (mode, operands[1]);
+ }
+ }
-int
-uns_arith_operand (rtx op, enum machine_mode mode)
-{
- return register_operand (op, mode) || uns_small_int (op, mode);
-}
+ /* Fixup TLS cases. */
+ if (tls_symbolic_operand (operands [1]))
+ operands[1] = legitimize_tls_address (operands[1]);
-/* 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)]);
-}
+ /* Fixup PIC cases. */
+ if (flag_pic && CONSTANT_P (operands[1]))
+ {
+ if (pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], mode, 0);
-/* Return 1 if OP is a valid operand for the source of a move insn. */
+ if (GET_CODE (operands[1]) == LABEL_REF && mode == SImode)
+ {
+ emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
+ return true;
+ }
-int
-input_operand (rtx op, enum machine_mode mode)
-{
- enum mode_class mclass;
+ if (GET_CODE (operands[1]) == LABEL_REF && mode == DImode)
+ {
+ gcc_assert (TARGET_ARCH64);
+ emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
+ return true;
+ }
- /* If both modes are non-void they must be the same. */
- if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
- return 0;
+ if (symbolic_operand (operands[1], mode))
+ {
+ operands[1] = legitimize_pic_address (operands[1],
+ mode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ return false;
+ }
+ }
- /* 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 we are trying to toss an integer constant into FP registers,
+ or loading a FP or vector constant, force it into memory. */
+ if (CONSTANT_P (operands[1])
+ && REG_P (operands[0])
+ && (SPARC_FP_REG_P (REGNO (operands[0]))
+ || SCALAR_FLOAT_MODE_P (mode)
+ || VECTOR_MODE_P (mode)))
+ {
+ /* emit_group_store will send such bogosity to us when it is
+ not storing directly into memory. So fix this up to avoid
+ crashes in output_constant_pool. */
+ if (operands [1] == const0_rtx)
+ operands[1] = CONST0_RTX (mode);
- /* 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;
+ /* We can clear FP registers if TARGET_VIS, and always other regs. */
+ if ((TARGET_VIS || REGNO (operands[0]) < SPARC_FIRST_FP_REG)
+ && const_zero_operand (operands[1], mode))
+ return false;
- if (register_operand (op, mode))
- return 1;
+ if (REGNO (operands[0]) < SPARC_FIRST_FP_REG
+ /* We are able to build any SF constant in integer registers
+ with at most 2 instructions. */
+ && (mode == SFmode
+ /* And any DF constant in integer registers. */
+ || (mode == DFmode
+ && (reload_completed || reload_in_progress))))
+ return false;
- 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;
+ operands[1] = force_const_mem (mode, operands[1]);
+ if (!reload_in_progress)
+ operands[1] = validize_mem (operands[1]);
+ return false;
+ }
- /* If this is a SUBREG, look inside so that we handle
- paradoxical ones. */
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
+ /* Accept non-constants and valid constants unmodified. */
+ if (!CONSTANT_P (operands[1])
+ || GET_CODE (operands[1]) == HIGH
+ || input_operand (operands[1], mode))
+ return false;
- /* Check for valid MEM forms. */
- if (GET_CODE (op) == MEM)
- return memory_address_p (mode, XEXP (op, 0));
+ switch (mode)
+ {
+ case QImode:
+ /* All QImode constants require only one insn, so proceed. */
+ break;
- return 0;
-}
+ case HImode:
+ case SImode:
+ sparc_emit_set_const32 (operands[0], operands[1]);
+ return true;
-/* Return 1 if OP is valid for the lhs of a compare insn. */
+ case DImode:
+ /* input_operand should have filtered out 32-bit mode. */
+ sparc_emit_set_const64 (operands[0], operands[1]);
+ return true;
+
+ default:
+ gcc_unreachable ();
+ }
-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);
+ return false;
}
-\f
-/* We know it can't be done in one insn when we get here,
- the movsi expander guarantees this. */
+/* Load OP1, a 32-bit constant, into OP0, a register.
+ We know it can't be done in one insn when we get
+ here, the move expander guarantees this. */
+
void
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);
-
- if (SPARC_SETHI_P (value & GET_MODE_MASK (mode))
- || SPARC_SIMM13_P (value))
- abort ();
- }
-
- /* Full 2-insn decomposition is needed. */
if (reload_in_progress || reload_completed)
temp = op0;
else
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,
gen_rtx_HIGH (mode, op1)));
emit_insn (gen_rtx_SET (VOIDmode,
op0, gen_rtx_LO_SUM (mode, temp, op1)));
-
}
}
-\f
/* Load OP1, a symbolic 64-bit constant, into OP0, a DImode register.
If TEMP is nonzero, we are forbidden to use any other scratch
registers. Otherwise, we are allowed to generate them as needed.
Note that TEMP may have TImode if the code model is TARGET_CM_MEDANY
or TARGET_CM_EMBMEDANY (see the reload_indi and reload_outdi patterns). */
+
void
sparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp)
{
it TImode). Pick the other one to use as our scratch. */
if (rtx_equal_p (temp, op0))
{
- if (ti_temp)
- temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
- else
- abort();
+ gcc_assert (ti_temp);
+ temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
}
temp1 = op0;
temp2 = temp; /* op0 is _not_ allowed, see above. */
it TImode). Pick the other one to use as our scratch. */
if (rtx_equal_p (temp, op0))
{
- if (ti_temp)
- temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
- else
- abort();
+ gcc_assert (ti_temp);
+ temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
}
temp1 = op0;
temp2 = temp; /* op0 is _not_ allowed, see above. */
break;
default:
- abort();
+ gcc_unreachable ();
}
}
+#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. */
-static void sparc_emit_set_safe_HIGH64 (rtx, HOST_WIDE_INT);
+static rtx gen_safe_HIGH64 (rtx, HOST_WIDE_INT);
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
during CSE. We mask out the non-HIGH bits, and matches
a plain movdi, to alleviate this problem. */
-static void
-sparc_emit_set_safe_HIGH64 (rtx dest, HOST_WIDE_INT val)
+static rtx
+gen_safe_HIGH64 (rtx dest, HOST_WIDE_INT val)
{
- emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_HIGHINT64 (val)));
+ return 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.
else
high_bits = low_bits;
- sparc_emit_set_safe_HIGH64 (temp, high_bits);
+ emit_insn (gen_safe_HIGH64 (temp, high_bits));
if (!is_neg)
{
emit_insn (gen_rtx_SET (VOIDmode, op0,
if ((high_bits & 0xfffffc00) != 0)
{
- sparc_emit_set_safe_HIGH64 (temp, high_bits);
+ emit_insn (gen_safe_HIGH64 (temp, high_bits));
if ((high_bits & ~0xfffffc00) != 0)
emit_insn (gen_rtx_SET (VOIDmode, op0,
gen_safe_OR64 (temp, (high_bits & 0x3ff))));
if ((high_bits & 0xfffffc00) != 0)
{
- sparc_emit_set_safe_HIGH64 (temp, high_bits);
+ emit_insn (gen_safe_HIGH64 (temp, high_bits));
if ((high_bits & ~0xfffffc00) != 0)
emit_insn (gen_rtx_SET (VOIDmode,
sub_temp,
gen_rtx_ASHIFT (DImode, sub_temp,
GEN_INT (32))));
- sparc_emit_set_safe_HIGH64 (temp2, low_bits);
+ emit_insn (gen_safe_HIGH64 (temp2, low_bits));
if ((low_bits & ~0xfffffc00) != 0)
{
emit_insn (gen_rtx_SET (VOIDmode, temp3,
}
/* If there are no bits set this should have gone out
as one instruction! */
- if (lowest_bit_set == -1
- || highest_bit_set == -1)
- abort ();
+ gcc_assert (lowest_bit_set != -1 && highest_bit_set != -1);
all_bits_between_are_set = 1;
for (i = lowest_bit_set; i <= highest_bit_set; i++)
{
lo = 0;
hi = ((high_bits >> (lowest_bit_set - 32)) << shift);
}
- if (hi & lo)
- abort ();
+ gcc_assert (! (hi & lo));
return (hi | lo);
}
rtx temp = 0;
/* Sanity check that we know what we are working with. */
- if (! TARGET_ARCH64)
- abort ();
-
- if (GET_CODE (op0) != SUBREG)
- {
- if (GET_CODE (op0) != REG
- || (REGNO (op0) >= SPARC_FIRST_FP_REG
- && REGNO (op0) <= SPARC_LAST_V9_FP_REG))
- abort ();
- }
+ gcc_assert (TARGET_ARCH64
+ && (GET_CODE (op0) == SUBREG
+ || (REG_P (op0) && ! SPARC_FP_REG_P (REGNO (op0)))));
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;
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 */
else if (lowest_bit_set == 0)
shift = -(63 - highest_bit_set);
- if (! SPARC_SIMM13_P (the_const))
- abort ();
+ gcc_assert (SPARC_SIMM13_P (the_const));
+ gcc_assert (shift != 0);
emit_insn (gen_safe_SET64 (temp, the_const));
if (shift > 0)
gen_rtx_LSHIFTRT (DImode,
temp,
GEN_INT (-shift))));
- else
- abort ();
return;
}
create_simple_focus_bits (high_bits, low_bits,
lowest_bit_set, 10);
- if (! SPARC_SETHI_P (focus_bits))
- abort ();
+ gcc_assert (SPARC_SETHI_P (focus_bits));
+ gcc_assert (lowest_bit_set != 10);
- sparc_emit_set_safe_HIGH64 (temp, focus_bits);
+ emit_insn (gen_safe_HIGH64 (temp, focus_bits));
/* If lowest_bit_set == 10 then a sethi alone could have done it. */
if (lowest_bit_set < 10)
op0,
gen_rtx_ASHIFT (DImode, temp,
GEN_INT (lowest_bit_set - 10))));
- else
- abort ();
return;
}
|| (((~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);
}
lowest_bit_set, 0);
/* We can't get here in this state. */
- if (highest_bit_set < 32
- || lowest_bit_set >= 32)
- abort ();
+ gcc_assert (highest_bit_set >= 32 && lowest_bit_set < 32);
/* So what we know is that the set bits straddle the
middle of the 64-bit word. */
#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,
return CCFPEmode;
default:
- abort ();
+ gcc_unreachable ();
}
}
else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
case CCFPmode :
break;
default :
- abort ();
+ gcc_unreachable ();
}
emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
int i;
/* We only expect to be called for conversions, unary, and binary ops. */
- if (nargs < 2 || nargs > 3)
- abort ();
+ gcc_assert (nargs == 2 || nargs == 3);
for (i = 0; i < nargs; ++i)
{
{
rtx ret;
- if (nargs != 2)
- abort ();
+ gcc_assert (nargs == 2);
ret = emit_library_call_value (func_sym, operands[0], LCT_NORMAL,
GET_MODE (operands[0]), 1,
func = "_Qp_div";
break;
default:
- abort ();
+ gcc_unreachable ();
}
emit_soft_tfmode_libcall (func, 3, operands);
{
const char *func;
- switch (code)
- {
- case SQRT:
- func = "_Qp_sqrt";
- break;
- default:
- abort ();
- }
+ gcc_assert (code == SQRT);
+ func = "_Qp_sqrt";
emit_soft_tfmode_libcall (func, 2, operands);
}
func = "_Qp_dtoq";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
func = "_Qp_qtod";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
func = "_Qp_xtoq";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
func = "_Qp_uxtoq";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
func = "_Qp_qtox";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
func = "_Qp_qtoux";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
emit_soft_tfmode_libcall (func, 2, operands);
case UNSPEC:
return true;
default:
- abort ();
+ gcc_unreachable ();
}
}
\f
-/* The table we use to reference PIC data. */
+/* PIC support. */
+static GTY(()) char pic_helper_symbol_name[256];
+static GTY(()) rtx pic_helper_symbol;
+static GTY(()) bool pic_helper_emitted_p = false;
static GTY(()) rtx global_offset_table;
-/* The function we use to get at it. */
-static GTY(()) rtx add_pc_to_pic_symbol;
-static GTY(()) char add_pc_to_pic_symbol_name[256];
-
/* Ensure that we are not using patterns that are not OK with PIC. */
int
switch (flag_pic)
{
case 1:
- if (GET_CODE (recog_data.operand[i]) == SYMBOL_REF
- || (GET_CODE (recog_data.operand[i]) == CONST
- && ! (GET_CODE (XEXP (recog_data.operand[i], 0)) == MINUS
- && (XEXP (XEXP (recog_data.operand[i], 0), 0)
- == global_offset_table)
- && (GET_CODE (XEXP (XEXP (recog_data.operand[i], 0), 1))
- == CONST))))
- abort ();
+ gcc_assert (GET_CODE (recog_data.operand[i]) != SYMBOL_REF
+ && (GET_CODE (recog_data.operand[i]) != CONST
+ || (GET_CODE (XEXP (recog_data.operand[i], 0)) == MINUS
+ && (XEXP (XEXP (recog_data.operand[i], 0), 0)
+ == global_offset_table)
+ && (GET_CODE (XEXP (XEXP (recog_data.operand[i], 0), 1))
+ == CONST))));
case 2:
default:
return 1;
/* Floating point constants are generally not ok.
The only exception is 0.0 in VIS. */
if (TARGET_VIS
- && (GET_MODE (x) == SFmode
- || GET_MODE (x) == DFmode
- || GET_MODE (x) == TFmode)
- && fp_zero_operand (x, GET_MODE (x)))
+ && SCALAR_FLOAT_MODE_P (GET_MODE (x))
+ && const_zero_operand (x, GET_MODE (x)))
+ return true;
+
+ return false;
+
+ case CONST_VECTOR:
+ /* Vector constants are generally not ok.
+ The only exception is 0 in VIS. */
+ if (TARGET_VIS
+ && const_zero_operand (x, GET_MODE (x)))
return true;
return false;
int
legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
{
- rtx rs1 = NULL, rs2 = NULL, imm1 = NULL, imm2;
+ rtx rs1 = NULL, rs2 = NULL, imm1 = NULL;
if (REG_P (addr) || GET_CODE (addr) == SUBREG)
rs1 = addr;
&& ! TARGET_CM_MEDMID
&& RTX_OK_FOR_OLO10_P (rs2))
{
- imm2 = rs2;
rs2 = NULL;
imm1 = XEXP (rs1, 1);
rs1 = XEXP (rs1, 0);
if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
return 0;
- if (USE_AS_OFFSETABLE_LO10)
- {
- /* We can't allow TFmode, because an offset greater than or equal to
- the alignment (8) may cause the LO_SUM to overflow if !v9. */
- if (mode == TFmode && ! TARGET_V9)
- return 0;
- }
- else
- {
- /* We prohibit LO_SUM for TFmode when there are no quad move insns
- and we consequently need to split. We do this because LO_SUM
- is not an offsettable address. If we get the situation in reload
- where source and destination of a movtf pattern are both MEMs with
- LO_SUM address, then only one of them gets converted to an
- offsettable address. */
- if (mode == TFmode
- && ! (TARGET_FPU && TARGET_ARCH64 && TARGET_HARD_QUAD))
- return 0;
- }
+ /* We can't allow TFmode in 32-bit mode, because an offset greater
+ than the alignment (8) may cause the LO_SUM to overflow. */
+ if (mode == TFmode && TARGET_ARCH32)
+ return 0;
}
else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr))
return 1;
{
rtx temp1, temp2, temp3, ret, o0, got, insn;
- if (no_new_pseudos)
- abort ();
+ gcc_assert (! no_new_pseudos);
if (GET_CODE (addr) == SYMBOL_REF)
switch (SYMBOL_REF_TLS_MODEL (addr))
break;
default:
- abort ();
+ gcc_unreachable ();
}
else
- abort (); /* for now ... */
+ gcc_unreachable (); /* for now ... */
return ret;
}
if (reg == 0)
{
- if (reload_in_progress || reload_completed)
- abort ();
- else
- reg = gen_reg_rtx (Pmode);
+ gcc_assert (! reload_in_progress && ! reload_completed);
+ reg = gen_reg_rtx (Pmode);
}
if (flag_pic == 2)
won't get confused into thinking that these two instructions
are loading in the true address of the symbol. If in the
future a PIC rtx exists, that should be used instead. */
- if (Pmode == SImode)
+ if (TARGET_ARCH64)
{
- emit_insn (gen_movsi_high_pic (temp_reg, orig));
- emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
+ emit_insn (gen_movdi_high_pic (temp_reg, orig));
+ emit_insn (gen_movdi_lo_sum_pic (temp_reg, temp_reg, orig));
}
else
{
- emit_insn (gen_movdi_high_pic (temp_reg, orig));
- emit_insn (gen_movdi_lo_sum_pic (temp_reg, temp_reg, orig));
+ emit_insn (gen_movsi_high_pic (temp_reg, orig));
+ emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
}
address = temp_reg;
}
if (reg == 0)
{
- if (reload_in_progress || reload_completed)
- abort ();
- else
- reg = gen_reg_rtx (Pmode);
+ gcc_assert (! reload_in_progress && ! reload_completed);
+ reg = gen_reg_rtx (Pmode);
}
- if (GET_CODE (XEXP (orig, 0)) == PLUS)
- {
- base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
- offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
- base == reg ? 0 : reg);
- }
- else
- abort ();
+ gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+ base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+ offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+ base == reg ? 0 : reg);
if (GET_CODE (offset) == CONST_INT)
{
offset = force_reg (Pmode, offset);
else
/* If we reach here, then something is seriously wrong. */
- abort ();
+ gcc_unreachable ();
}
return gen_rtx_PLUS (Pmode, base, offset);
}
return x;
}
-/* Emit the special PIC prologue. */
+/* Emit the special PIC helper function. */
static void
-load_pic_register (void)
+emit_pic_helper (void)
{
- int orig_flag_pic = flag_pic;
+ const char *pic_name = reg_names[REGNO (pic_offset_table_rtx)];
+ int align;
- /* If we haven't emitted the special helper function, do so now. */
- if (add_pc_to_pic_symbol_name[0] == 0)
- {
- const char *pic_name = reg_names[REGNO (pic_offset_table_rtx)];
- int align;
+ text_section ();
+
+ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ if (align > 0)
+ ASM_OUTPUT_ALIGN (asm_out_file, align);
+ ASM_OUTPUT_LABEL (asm_out_file, pic_helper_symbol_name);
+ if (flag_delayed_branch)
+ fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
+ pic_name, pic_name);
+ else
+ fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
+ pic_name, pic_name);
+
+ pic_helper_emitted_p = true;
+}
- ASM_GENERATE_INTERNAL_LABEL (add_pc_to_pic_symbol_name, "LADDPC", 0);
- text_section ();
+/* Emit code to load the PIC register. */
- align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
- if (align > 0)
- ASM_OUTPUT_ALIGN (asm_out_file, align);
- ASM_OUTPUT_LABEL (asm_out_file, add_pc_to_pic_symbol_name);
- if (flag_delayed_branch)
- fprintf (asm_out_file, "\tjmp %%o7+8\n\t add\t%%o7, %s, %s\n",
- pic_name, pic_name);
- else
- fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp %%o7+8\n\t nop\n",
- pic_name, pic_name);
+static void
+load_pic_register (bool delay_pic_helper)
+{
+ int orig_flag_pic = flag_pic;
+
+ /* If we haven't initialized the special PIC symbols, do so now. */
+ if (!pic_helper_symbol_name[0])
+ {
+ ASM_GENERATE_INTERNAL_LABEL (pic_helper_symbol_name, "LADDPC", 0);
+ pic_helper_symbol = gen_rtx_SYMBOL_REF (Pmode, pic_helper_symbol_name);
+ global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
}
- /* Initialize every time through, since we can't easily
- know this to be permanent. */
- global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
- add_pc_to_pic_symbol = gen_rtx_SYMBOL_REF (Pmode, add_pc_to_pic_symbol_name);
+ /* If we haven't emitted the special PIC helper function, do so now unless
+ we are requested to delay it. */
+ if (!delay_pic_helper && !pic_helper_emitted_p)
+ emit_pic_helper ();
flag_pic = 0;
if (TARGET_ARCH64)
emit_insn (gen_load_pcrel_symdi (pic_offset_table_rtx, global_offset_table,
- add_pc_to_pic_symbol));
+ pic_helper_symbol));
else
emit_insn (gen_load_pcrel_symsi (pic_offset_table_rtx, global_offset_table,
- add_pc_to_pic_symbol));
+ pic_helper_symbol));
flag_pic = orig_flag_pic;
/* Need to emit this whether or not we obey regdecls,
return 0;
/* Obviously... */
- if (MEM_ALIGN (mem) / BITS_PER_UNIT >= (unsigned)desired)
+ if (!TARGET_UNALIGNED_DOUBLES
+ && MEM_ALIGN (mem) / BITS_PER_UNIT >= (unsigned)desired)
return 1;
/* ??? The rest of the function predates MEM_ALIGN so
/* Make sure nothing can clobber our register windows.
If a SAVE must be done, or there is a stack-local variable,
- the register window area must be allocated.
- ??? For v8 we apparently need an additional 8 bytes of reserved space. */
+ the register window area must be allocated. */
if (! leaf_function_p || size > 0)
- actual_fsize += (16 * UNITS_PER_WORD) + (TARGET_ARCH64 ? 0 : 8);
+ actual_fsize += FIRST_PARM_OFFSET (current_function_decl);
return SPARC_STACK_ALIGN (actual_fsize);
}
/* Emit code to save call-saved registers. */
static void
-emit_save_regs (void)
+emit_save_or_restore_regs (int action)
{
HOST_WIDE_INT offset;
rtx base;
offset = frame_base_offset - apparent_fsize;
- if (offset < -4096 || offset + num_gfregs * 4 > 4096)
+ if (offset < -4096 || offset + num_gfregs * 4 > 4095)
{
/* ??? This might be optimized a little as %g1 might already have a
value close enough that a single add insn will do. */
else
base = frame_base_reg;
- offset = save_or_restore_regs (0, 8, base, offset, SORR_SAVE);
- save_or_restore_regs (32, TARGET_V9 ? 96 : 64, base, offset, SORR_SAVE);
-}
-
-/* Emit code to restore call-saved registers. */
-
-static void
-emit_restore_regs (void)
-{
- HOST_WIDE_INT offset;
- rtx base;
-
- offset = frame_base_offset - apparent_fsize;
-
- if (offset < -4096 || offset + num_gfregs * 4 > 4096 - 8 /*double*/)
- {
- base = gen_rtx_REG (Pmode, 1);
- emit_move_insn (base, GEN_INT (offset));
- emit_insn (gen_rtx_SET (VOIDmode,
- base,
- gen_rtx_PLUS (Pmode, frame_base_reg, base)));
- offset = 0;
- }
- else
- base = frame_base_reg;
-
- offset = save_or_restore_regs (0, 8, base, offset, SORR_RESTORE);
- save_or_restore_regs (32, TARGET_V9 ? 96 : 64, base, offset, SORR_RESTORE);
+ offset = save_or_restore_regs (0, 8, base, offset, action);
+ save_or_restore_regs (32, TARGET_V9 ? 96 : 64, base, offset, action);
}
/* Generate a save_register_window insn. */
RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, i)) = 1;
}
- /* Call-saved registers are saved just above the outgoing argument area. */
if (num_gfregs)
- emit_save_regs ();
+ emit_save_or_restore_regs (SORR_SAVE);
/* Load the PIC register if needed. */
if (flag_pic && current_function_uses_pic_offset_table)
- load_pic_register ();
+ load_pic_register (false);
}
/* This function generates the assembly code for function entry, which boils
- down to emitting the necessary .register directives.
-
- ??? Historical cruft: "On SPARC, move-double insns between fpu and cpu need
- an 8-byte block of memory. If any fpu reg is used in the function, we
- allocate such a block here, at the bottom of the frame, just in case it's
- needed." Could this explain the -8 in emit_restore_regs? */
+ down to emitting the necessary .register directives. */
static void
sparc_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
/* Check that the assumption we made in sparc_expand_prologue is valid. */
- if (sparc_leaf_function_p != current_function_uses_only_leaf_regs)
- abort();
+ gcc_assert (sparc_leaf_function_p == current_function_uses_only_leaf_regs);
sparc_output_scratch_registers (file);
}
sparc_expand_epilogue (void)
{
if (num_gfregs)
- emit_restore_regs ();
+ emit_save_or_restore_regs (SORR_RESTORE);
if (actual_fsize == 0)
/* do nothing. */ ;
return;
}
- if (GET_CODE (pat) != SET)
- abort ();
+ gcc_assert (GET_CODE (pat) == SET);
operands[0] = SET_DEST (pat);
pat = SET_SRC (pat);
break;
case ASHIFT:
operands[1] = XEXP (pat, 0);
- if (XEXP (pat, 1) != const1_rtx)
- abort();
+ gcc_assert (XEXP (pat, 1) == const1_rtx);
output_asm_insn (" restore %r1, %r1, %Y0", operands);
break;
default:
semantics of restore/return. We simply output the jump to the
return address and the insn in the delay slot (if any). */
- if (current_function_calls_eh_return)
- abort ();
+ gcc_assert (! current_function_calls_eh_return);
return "jmp\t%%o7+%)%#";
}
{
/* If the function uses __builtin_eh_return, the eh_return
machinery occupies the delay slot. */
- if (final_sequence)
- abort ();
+ gcc_assert (! final_sequence);
if (! flag_delayed_branch)
fputs ("\tadd\t%fp, %g1, %fp\n", asm_out_file);
rtx delay, pat;
delay = NEXT_INSN (insn);
- if (! delay)
- abort ();
+ gcc_assert (delay);
pat = PATTERN (delay);
{
rtx operands[1];
- if (! flag_delayed_branch)
- abort();
+ gcc_assert (flag_delayed_branch);
operands[0] = call_operand;
register window. We simply output the jump to the function and
the insn in the delay slot (if any). */
- if (LEAF_SIBCALL_SLOT_RESERVED_P && final_sequence)
- abort();
+ gcc_assert (!(LEAF_SIBCALL_SLOT_RESERVED_P && final_sequence));
if (final_sequence)
output_asm_insn ("sethi\t%%hi(%a0), %%g1\n\tjmp\t%%g1 + %%lo(%a0)%#",
if (final_sequence)
{
rtx delay = NEXT_INSN (insn);
- if (! delay)
- abort ();
+ gcc_assert (delay);
output_restore (PATTERN (delay));
if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
{
/* The SPARC port defines no floating-point vector modes. */
- if (mode != BLKmode)
- abort ();
+ gcc_assert (mode == BLKmode);
}
else
{
mode or an integral mode, because we are guaranteed
by pass_by_reference that their size is not greater
than 16 bytes and TImode is 16-byte wide. */
- if (mode == BLKmode)
- abort ();
+ gcc_assert (mode != BLKmode);
/* Vector integers are handled like floats according to
the Sun VIS SDK. */
/* MODE is VOIDmode when generating the actual call. */
return -1;
- if (mode != BLKmode)
- abort ();
+ gcc_assert (mode == BLKmode);
/* For SPARC64, objects requiring 16-byte alignment get it. */
if (TARGET_ARCH64
break;
default :
- abort ();
+ gcc_unreachable ();
}
*pregno = regno;
if (nregs + slotno > SPARC_INT_ARG_MAX)
nregs = SPARC_INT_ARG_MAX - slotno;
}
- if (nregs == 0)
- abort ();
+ gcc_assert (nregs != 0);
parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (parms.stack + nregs));
function_arg_record_value_2 (type, 0, &parms, false);
function_arg_record_value_3 (typesize * BITS_PER_UNIT, &parms);
- if (parms.nregs != nregs)
- abort ();
+ gcc_assert (parms.nregs == nregs);
return parms.ret;
}
/* Structures up to 16 bytes in size are passed in arg slots on the
stack and are promoted to registers where possible. */
- if (int_size_in_bytes (type) > 16)
- abort (); /* shouldn't get here */
+ gcc_assert (int_size_in_bytes (type) <= 16);
return function_arg_record_value (type, mode, slotno, named, regbase);
}
{
HOST_WIDE_INT size = int_size_in_bytes (type);
- if (size > 16)
- abort (); /* shouldn't get here */
+ gcc_assert (size <= 16);
return function_arg_union_value (size, mode, slotno, regno);
}
instructions are enabled. */
HOST_WIDE_INT size = int_size_in_bytes (type);
- if (size > 16)
- abort (); /* shouldn't get here */
+ gcc_assert (size <= 16);
if (mode == BLKmode)
return function_arg_vector_value (size,
instructions are enabled. */
HOST_WIDE_INT size = int_size_in_bytes (type);
- if ((TARGET_ARCH32 && size > 8) || (TARGET_ARCH64 && size > 32))
- abort (); /* shouldn't get here */
+ gcc_assert ((TARGET_ARCH32 && size <= 8)
+ || (TARGET_ARCH64 && size <= 32));
if (mode == BLKmode)
return function_arg_vector_value (size,
/* Structures up to 32 bytes in size are passed in registers,
promoted to fp registers where possible. */
- if (int_size_in_bytes (type) > 32)
- abort (); /* shouldn't get here */
+ gcc_assert (int_size_in_bytes (type) <= 32);
return function_arg_record_value (type, mode, 0, 1, regbase);
}
{
HOST_WIDE_INT size = int_size_in_bytes (type);
- if (size > 32)
- abort (); /* shouldn't get here */
+ gcc_assert (size <= 32);
return function_arg_union_value (size, mode, 0, regbase);
}
in a mode corresponding to the size of the type. */
HOST_WIDE_INT bytes = int_size_in_bytes (type);
- if (bytes > 32)
- abort (); /* shouldn't get here */
+ gcc_assert (bytes <= 32);
mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* ??? !v9: FP branches cannot be preceded by another floating point
break;
default:
- abort ();
+ gcc_unreachable ();
}
strcpy (string, branch);
}
labelno = v9_fcc_labelno;
if (v8)
{
- if (REGNO (cc_reg) == SPARC_FCC_REG)
- labelno = "";
- else
- abort ();
+ gcc_assert (REGNO (cc_reg) == SPARC_FCC_REG);
+ labelno = "";
}
}
else if (mode == CCXmode || mode == CCX_NOOVmode)
{
labelno = "%%xcc, ";
- if (v8)
- abort ();
+ gcc_assert (! v8);
}
else
{
break;
default:
- abort();
- break;
+ gcc_unreachable ();
}
if (TARGET_ARCH64)
if (GET_CODE (x) != MEM)
{
slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, x));
+ emit_move_insn (slot0, x);
}
else
slot0 = x;
if (GET_CODE (y) != MEM)
{
slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, y));
+ emit_move_insn (slot1, y);
}
else
slot1 = y;
code = reverse_condition (code);
/* Only 64 bit versions of these instructions exist. */
- if (mode != DImode)
- abort ();
+ gcc_assert (mode == DImode);
/* Start by writing the branch condition. */
break;
default:
- abort ();
+ gcc_unreachable ();
}
p = strchr (string, '\0');
sparc_splitdi_legitimate (rtx reg, rtx mem)
{
/* Punt if we are here by mistake. */
- if (! reload_completed)
- abort ();
+ gcc_assert (reload_completed);
/* We must have an offsettable memory reference. */
if (! offsettable_memref_p (mem))
else if (GET_MODE (x) == CCXmode)
fputs ("%xcc", file);
else
- abort ();
+ gcc_unreachable ();
}
else
/* %fccN register */
case VECTOR_TYPE:
case CHAR_TYPE: /* GNU Pascal CHAR type. Not used in C. */
case BOOLEAN_TYPE: /* GNU Fortran BOOLEAN type. */
- case FILE_TYPE: /* GNU Pascal FILE type. */
case LANG_TYPE: /* ? */
return qualifiers;
default:
- abort (); /* Not a type! */
+ gcc_unreachable (); /* Not a type! */
}
}
return;
/* Align to cache line in the function's code section. */
- function_section (current_function_decl);
+ current_function_section (current_function_decl);
align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
if (align > 0)
int set_once = 0;
rtx y = x;
- if (GET_CODE (x) != REG)
- abort ();
+ gcc_assert (GET_CODE (x) == REG);
if (GET_MODE (x) == DImode)
y = gen_rtx_REG (SImode, REGNO (x) + WORDS_BIG_ENDIAN);
break;
case 'Y':
- return fp_zero_operand (op, GET_MODE (op));
+ return const_zero_operand (op, GET_MODE (op));
default:
return 0;
return true;
case CONST_DOUBLE:
- if (GET_MODE (x) == DImode
- && ((XINT (x, 3) == 0
- && (unsigned HOST_WIDE_INT) XINT (x, 2) < 0x1000)
- || (XINT (x, 3) == -1
- && XINT (x, 2) < 0
- && XINT (x, 2) >= -0x1000)))
+ if (GET_MODE (x) == VOIDmode
+ && ((CONST_DOUBLE_HIGH (x) == 0
+ && CONST_DOUBLE_LOW (x) < 0x1000)
+ || (CONST_DOUBLE_HIGH (x) == -1
+ && CONST_DOUBLE_LOW (x) < 0
+ && CONST_DOUBLE_LOW (x) >= -0x1000)))
*total = 0;
else
*total = 8;
nbits++;
}
else if (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
- && GET_MODE (XEXP (x, 1)) == DImode)
+ && GET_MODE (XEXP (x, 1)) == VOIDmode)
{
rtx x1 = XEXP (x, 1);
- unsigned HOST_WIDE_INT value1 = XINT (x1, 2);
- unsigned HOST_WIDE_INT value2 = XINT (x1, 3);
+ unsigned HOST_WIDE_INT value1 = CONST_DOUBLE_LOW (x1);
+ unsigned HOST_WIDE_INT value2 = CONST_DOUBLE_HIGH (x1);
for (nbits = 0; value1 != 0; value1 &= value1 - 1)
nbits++;
rtx vcall_offset_rtx = GEN_INT (vcall_offset);
rtx scratch = gen_rtx_REG (Pmode, 1);
- if (vcall_offset >= 0)
- abort ();
+ gcc_assert (vcall_offset < 0);
/* SCRATCH = *THIS. */
emit_move_insn (scratch, gen_rtx_MEM (Pmode, this));
{
spill_reg = gen_rtx_REG (word_mode, 15); /* %o7 */
start_sequence ();
- load_pic_register (); /* clobbers %o7 */
+ /* Delay emitting the PIC helper function because it needs to
+ change the section and we are emitting assembly code. */
+ load_pic_register (true); /* clobbers %o7 */
scratch = legitimize_pic_address (funexp, Pmode, scratch);
seq = get_insns ();
end_sequence ();
break;
default:
- abort();
+ gcc_unreachable ();
}
}
&& for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
return cfun->machine->some_ld_name;
- abort ();
+ gcc_unreachable ();
}
static int
fputs ("\t.xword\t%r_tls_dtpoff64(", file);
break;
default:
- abort ();
+ gcc_unreachable ();
}
output_addr_const (file, x);
fputs (")", file);
}
+static
+void sparc_file_end (void)
+{
+ /* If we haven't emitted the special PIC helper function, do so now. */
+ if (pic_helper_symbol_name[0] && !pic_helper_emitted_p)
+ emit_pic_helper ();
+
+ if (NEED_INDICATE_EXEC_STACK)
+ file_end_indicate_exec_stack ();
+}
+
#include "gt-sparc.h"