static void ia64_encode_section_info (tree, rtx, int);
static rtx ia64_struct_value_rtx (tree, int);
static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
+static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
\f
/* Table of valid machine attributes. */
#undef TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
#define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK ia64_dependencies_evaluation_hook
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
-
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ia64_first_cycle_multipass_dfa_lookahead
#undef TARGET_UNWIND_EMIT
#define TARGET_UNWIND_EMIT process_for_unwind_directive
-struct gcc_target targetm = TARGET_INITIALIZER;
-\f
-/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- if (mode != GET_MODE (op) && mode != VOIDmode)
- return 0;
-
- return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG
- || (GET_CODE (op) == SUBREG && GET_CODE (XEXP (op, 0)) == REG));
-}
-
-/* Return 1 if OP refers to a symbol in the sdata section. */
-
-int
-sdata_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- if (GET_CODE (XEXP (op, 0)) != PLUS
- || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF)
- break;
- op = XEXP (XEXP (op, 0), 0);
- /* FALLTHRU */
-
- case SYMBOL_REF:
- if (CONSTANT_POOL_ADDRESS_P (op))
- return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
- else
- return SYMBOL_REF_LOCAL_P (op) && SYMBOL_REF_SMALL_P (op);
-
- default:
- break;
- }
-
- return 0;
-}
-
-int
-small_addr_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return SYMBOL_REF_SMALL_ADDR_P (op);
-}
-
-/* Return 1 if OP refers to a symbol, and is appropriate for a GOT load. */
-
-int
-got_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS)
- return 0;
- if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
- return 0;
- op = XEXP (op, 1);
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- return 1;
-
- /* Ok if we're not using GOT entries at all. */
- if (TARGET_NO_PIC || TARGET_AUTO_PIC)
- return 1;
-
- /* "Ok" while emitting rtl, since otherwise we won't be provided
- with the entire offset during emission, which makes it very
- hard to split the offset into high and low parts. */
- if (rtx_equal_function_value_matters)
- return 1;
-
- /* Force the low 14 bits of the constant to zero so that we do not
- use up so many GOT entries. */
- return (INTVAL (op) & 0x3fff) == 0;
-
- case SYMBOL_REF:
- if (SYMBOL_REF_SMALL_ADDR_P (op))
- return 0;
- case LABEL_REF:
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Return 1 if OP refers to a symbol. */
-
-int
-symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Return tls_model if OP refers to a TLS symbol. */
-
-int
-tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
- return SYMBOL_REF_TLS_MODEL (op);
-}
-
-
-/* Return 1 if OP refers to a function. */
-
-int
-function_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (op))
- return 1;
- else
- return 0;
-}
-
-/* Return 1 if OP is setjmp or a similar function. */
-
-/* ??? This is an unsatisfying solution. Should rethink. */
-
-int
-setjmp_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- const char *name;
- int retval = 0;
-
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
-
- name = XSTR (op, 0);
-
- /* The following code is borrowed from special_function_p in calls.c. */
-
- /* Disregard prefix _, __ or __x. */
- if (name[0] == '_')
- {
- if (name[1] == '_' && name[2] == 'x')
- name += 3;
- else if (name[1] == '_')
- name += 2;
- else
- name += 1;
- }
-
- if (name[0] == 's')
- {
- retval
- = ((name[1] == 'e'
- && (! strcmp (name, "setjmp")
- || ! strcmp (name, "setjmp_syscall")))
- || (name[1] == 'i'
- && ! strcmp (name, "sigsetjmp"))
- || (name[1] == 'a'
- && ! strcmp (name, "savectx")));
- }
- else if ((name[0] == 'q' && name[1] == 's'
- && ! strcmp (name, "qsetjmp"))
- || (name[0] == 'v' && name[1] == 'f'
- && ! strcmp (name, "vfork")))
- retval = 1;
-
- return retval;
-}
-
-/* Return 1 if OP is a general operand, excluding tls symbolic operands. */
-
-int
-move_operand (rtx op, enum machine_mode mode)
-{
- return general_operand (op, mode) && !tls_symbolic_operand (op, mode);
-}
-
-/* Return 1 if OP is a register operand that is (or could be) a GR reg. */
-
-int
-gr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) an FR reg. */
-
-int
-fr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) a GR/FR reg. */
-
-int
-grfr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a GR reg. */
-
-int
-gr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a FR reg. */
-
-int
-fr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is a GR/FR reg. */
-
-int
-grfr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a GR register operand, or zero. */
-
-int
-gr_reg_or_0_operand (rtx op, enum machine_mode mode)
-{
- return (op == const0_rtx || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 5 bit immediate operand. */
-
-int
-gr_reg_or_5bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 32)
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 6 bit immediate operand. */
-
-int
-gr_reg_or_6bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or an 8 bit immediate operand. */
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P ia64_scalar_mode_supported_p
-int
-gr_reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR/FR register operand, or an 8 bit immediate. */
-
-int
-grfr_reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
- || grfr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or an 8 bit adjusted immediate
- operand. */
-
-int
-gr_reg_or_8bit_adjusted_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or is valid for both an 8 bit
- immediate and an 8 bit adjusted immediate operand. This is necessary
- because when we emit a compare, we don't know what the condition will be,
- so we need the union of the immediates accepted by GT and LT. */
-
-int
-gr_reg_or_8bit_and_adjusted_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))
- && CONST_OK_FOR_L (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 14 bit immediate operand. */
-
-int
-gr_reg_or_14bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 22 bit immediate operand. */
-
-int
-gr_reg_or_22bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a 6 bit immediate operand. */
-
-int
-shift_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)));
-}
-
-/* Return 1 if OP is a 5 bit immediate operand. */
-
-int
-shift_32bit_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= 0 && INTVAL (op) < 32));
-}
-
-/* Return 1 if OP is a 2, 4, 8, or 16 immediate operand. */
-
-int
-shladd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) == 2 || INTVAL (op) == 4
- || INTVAL (op) == 8 || INTVAL (op) == 16));
-}
-
-/* Return 1 if OP is a -16, -8, -4, -1, 1, 4, 8, or 16 immediate operand. */
-
-int
-fetchadd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) == -16 || INTVAL (op) == -8 ||
- INTVAL (op) == -4 || INTVAL (op) == -1 ||
- INTVAL (op) == 1 || INTVAL (op) == 4 ||
- INTVAL (op) == 8 || INTVAL (op) == 16));
-}
-
-/* Return 1 if OP is a floating-point constant zero, one, or a register. */
-
-int
-fr_reg_or_fp01_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (op))
- || fr_register_operand (op, mode));
-}
-
-/* Like nonimmediate_operand, but don't allow MEMs that try to use a
- POST_MODIFY with a REG as displacement. */
-
-int
-destination_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM
- && GET_CODE (XEXP (op, 0)) == POST_MODIFY
- && GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) == REG)
- return 0;
- return 1;
-}
-
-/* Like memory_operand, but don't allow post-increments. */
-
-int
-not_postinc_memory_operand (rtx op, enum machine_mode mode)
-{
- return (memory_operand (op, mode)
- && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC);
-}
-
-/* Return 1 if this is a comparison operator, which accepts a normal 8-bit
- signed immediate operand. */
-
-int
-normal_comparison_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == EQ || code == NE
- || code == GT || code == LE || code == GTU || code == LEU));
-}
-
-/* Return 1 if this is a comparison operator, which accepts an adjusted 8-bit
- signed immediate operand. */
-
-int
-adjusted_comparison_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == LT || code == GE || code == LTU || code == GEU));
-}
-
-/* Return 1 if this is a signed inequality operator. */
-
-int
-signed_inequality_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == GE || code == GT
- || code == LE || code == LT));
-}
-
-/* Return 1 if this operator is valid for predication. */
-
-int
-predicate_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && (code == EQ || code == NE));
-}
-
-/* Return 1 if this operator can be used in a conditional operation. */
-
-int
-condop_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && (code == PLUS || code == MINUS || code == AND
- || code == IOR || code == XOR));
-}
-
-/* Return 1 if this is the ar.lc register. */
-
-int
-ar_lc_reg_operand (register rtx op, enum machine_mode mode)
-{
- return (GET_MODE (op) == DImode
- && (mode == DImode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_LC_REGNUM);
-}
-
-/* Return 1 if this is the ar.ccv register. */
-
-int
-ar_ccv_reg_operand (register rtx op, enum machine_mode mode)
-{
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_CCV_REGNUM);
-}
-
-/* Return 1 if this is the ar.pfs register. */
-
-int
-ar_pfs_reg_operand (register rtx op, enum machine_mode mode)
-{
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_PFS_REGNUM);
-}
-
-/* Like general_operand, but don't allow (mem (addressof)). */
-
-int
-general_xfmode_operand (rtx op, enum machine_mode mode)
-{
- if (! general_operand (op, mode))
- return 0;
- return 1;
-}
-
-/* Similarly. */
-
-int
-destination_xfmode_operand (rtx op, enum machine_mode mode)
-{
- if (! destination_operand (op, mode))
- return 0;
- return 1;
-}
-
-/* Similarly. */
-
-int
-xfreg_or_fp01_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG)
- return 0;
- return fr_reg_or_fp01_operand (op, mode);
-}
-
-/* Return 1 if OP is valid as a base register in a reg + offset address. */
-
-int
-basereg_operand (rtx op, enum machine_mode mode)
-{
- /* ??? Should I copy the flag_omit_frame_pointer and cse_not_expected
- checks from pa.c basereg_operand as well? Seems to be OK without them
- in test runs. */
-
- return (register_operand (op, mode) &&
- REG_POINTER ((GET_CODE (op) == SUBREG) ? SUBREG_REG (op) : op));
-}
+struct gcc_target targetm = TARGET_INITIALIZER;
\f
typedef enum
{
void
ia64_expand_load_address (rtx dest, rtx src)
{
- if (tls_symbolic_operand (src, VOIDmode))
+ if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (src))
abort ();
if (GET_CODE (dest) != REG)
abort ();
if (GET_CODE (src) == CONST
&& GET_CODE (XEXP (src, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (src, 0), 1)) == CONST_INT
- && (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x1fff) != 0)
+ && (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x3fff) != 0)
{
rtx sym = XEXP (XEXP (src, 0), 0);
HOST_WIDE_INT ofs, hi, lo;
gen_thread_pointer (void)
{
if (!thread_pointer_rtx)
- {
- thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
- RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
- }
+ thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
return thread_pointer_rtx;
}
tga_op1 = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
- tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
- RTX_UNCHANGING_P (tga_op1) = 1;
+ tga_op1 = gen_const_mem (Pmode, tga_op1);
tga_op2 = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
- tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
- RTX_UNCHANGING_P (tga_op2) = 1;
+ tga_op2 = gen_const_mem (Pmode, tga_op2);
tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
LCT_CONST, Pmode, 2, tga_op1,
tga_op1 = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
- tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
- RTX_UNCHANGING_P (tga_op1) = 1;
+ tga_op1 = gen_const_mem (Pmode, tga_op1);
tga_op2 = const0_rtx;
case TLS_MODEL_INITIAL_EXEC:
tmp = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_tprel (tmp, op1));
- tmp = gen_rtx_MEM (Pmode, tmp);
- RTX_UNCHANGING_P (tmp) = 1;
+ tmp = gen_const_mem (Pmode, tmp);
tmp = force_reg (Pmode, tmp);
if (!register_operand (op0, Pmode))
if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))
{
enum tls_model tls_kind;
- if ((tls_kind = tls_symbolic_operand (op1, VOIDmode)))
+ if (GET_CODE (op1) == SYMBOL_REF
+ && (tls_kind = SYMBOL_REF_TLS_MODEL (op1)))
return ia64_expand_tls_address (tls_kind, op0, op1);
if (!TARGET_NO_PIC && reload_completed)
if (optimize)
{
edge e;
+ edge_iterator ei;
- for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
if ((e->flags & EDGE_FAKE) == 0
&& (e->flags & EDGE_FALLTHRU) != 0)
break;
preserve those input registers used as arguments to the sibling call.
It is unclear how to compute that number here. */
if (current_frame_info.n_input_regs != 0)
- emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
- const0_rtx, const0_rtx,
- GEN_INT (current_frame_info.n_input_regs),
- const0_rtx));
+ {
+ rtx n_inputs = GEN_INT (current_frame_info.n_input_regs);
+ insn = emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
+ const0_rtx, const0_rtx,
+ n_inputs, const0_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
}
else if (gr_size > UNITS_PER_WORD)
int_regs += gr_size / UNITS_PER_WORD;
}
-
- /* If we ended up using just one location, just return that one loc, but
- change the mode back to the argument mode. However, we can't do this
- when hfa_mode is XFmode and mode is TImode. In that case, we would
- return a TImode reference to an FP reg, but FP regs can't hold TImode.
- We need the PARALLEL to make this work. This can happen for a union
- containing a single __float80 member. */
- if (i == 1 && ! (hfa_mode == XFmode && mode == TImode))
- return gen_rtx_REG (mode, REGNO (XEXP (loc[0], 0)));
- else
- return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
/* Integral and aggregates go in general registers. If we have run out of
cum->fp_regs = fp_regs;
}
- /* Integral and aggregates go in general registers. If we have run out of
- FR registers, then FP values must also go in general registers. This can
- happen when we have a SFmode HFA. */
- else if (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS)
+ /* Integral and aggregates go in general registers. So do TFmode FP values.
+ If we have run out of FR registers, then other FP values must also go in
+ general registers. This can happen when we have a SFmode HFA. */
+ else if (mode == TFmode || mode == TCmode
+ || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
cum->int_regs = cum->words;
/* If there is a prototype, then FP values go in a FR register when
}
}
+/* Arguments with alignment larger than 8 bytes start at the next even
+ boundary. On ILP32 HPUX, TFmode arguments start on next even boundary
+ even though their normal alignment is 8 bytes. See ia64_function_arg. */
+
+int
+ia64_function_arg_boundary (enum machine_mode mode, tree type)
+{
+
+ if (mode == TFmode && TARGET_HPUX && TARGET_ILP32)
+ return PARM_BOUNDARY * 2;
+
+ if (type)
+ {
+ if (TYPE_ALIGN (type) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
+ }
+
+ if (GET_MODE_BITSIZE (mode) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
+}
+
/* Variable sized types are passed by reference. */
/* ??? At present this is a GCC extension to the IA-64 ABI. */
static bool
ia64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
{
+ /* We can't perform a sibcall if the current function has the syscall_linkage
+ attribute. */
+ if (lookup_attribute ("syscall_linkage",
+ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+ return false;
+
/* We must always return with our current GP. This means we can
only sibcall to functions defined in the current module. */
return decl && (*targetm.binds_local_p) (decl);
{
tree ptrtype = build_pointer_type (type);
tree addr = std_gimplify_va_arg_expr (valist, ptrtype, pre_p, post_p);
- return build_fold_indirect_ref (addr);
+ return build_va_arg_indirect_ref (addr);
}
/* Aggregate arguments with alignment larger than 8 bytes start at
? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
{
tree t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
- build_int_2 (2 * UNITS_PER_WORD - 1, 0));
+ build_int_cst (NULL_TREE, 2 * UNITS_PER_WORD - 1));
t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
- build_int_2 (-2 * UNITS_PER_WORD, -1));
+ build_int_cst (NULL_TREE, -2 * UNITS_PER_WORD));
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
gimplify_and_add (t, pre_p);
}
GEN_INT (offset));
offset += hfa_size;
}
-
- if (i == 1)
- return XEXP (loc[0], 0);
- else
- return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
else if (FLOAT_TYPE_P (valtype) && mode != TFmode && mode != TCmode)
return gen_rtx_REG (mode, FR_ARG_FIRST);
}
/* For all ASM_OPERANDS, we must traverse the vector of input operands.
- We can not just fall through here since then we would be confused
+ We cannot just fall through here since then we would be confused
by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
traditional asms unlike their normal usage. */
HOST_WIDE_INT bit = (offset >> 3) & 63;
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
- new_flags.is_write = (XINT (x, 1) == 1);
+ new_flags.is_write = (XINT (x, 1) == UNSPEC_GR_SPILL);
need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + bit,
new_flags, pred);
break;
static rtx dfa_pre_cycle_insn;
-/* We are about to being issuing INSN. Return nonzero if we can not
+/* We are about to being issuing INSN. Return nonzero if we cannot
issue it on given cycle CLOCK and return zero if we should not sort
the ready queue on the next clock start. */
by structure bundle_state (see above). If we generate the same
bundle state (key is automaton state after issuing the insns and
nops for it), we reuse already generated one. As consequence we
- reject some decisions which can not improve the solution and
+ reject some decisions which cannot improve the solution and
reduce memory for the algorithm.
When we reach the end of EBB (extended basic block), we choose the
{
dest_regno = REGNO (dest);
- /* If this isn't the final destination for ar.pfs, the alloc
- shouldn't have been marked frame related. */
- if (dest_regno != current_frame_info.reg_save_ar_pfs)
- abort ();
-
- fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ /* If this is the final destination for ar.pfs, then this must
+ be the alloc in the prologue. */
+ if (dest_regno == current_frame_info.reg_save_ar_pfs)
+ fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
+ ia64_dbx_register_number (dest_regno));
+ else
+ {
+ /* This must be an alloc before a sibcall. We must drop the
+ old frame info. The easiest way to drop the old frame
+ info is to ensure we had a ".restore sp" directive
+ followed by a new prologue. If the procedure doesn't
+ have a memory-stack frame, we'll issue a dummy ".restore
+ sp" now. */
+ if (current_frame_info.total_size == 0)
+ /* if haven't done process_epilogue() yet, do it now */
+ process_epilogue ();
+ fprintf (asm_out_file, "\t.prologue\n");
+ }
return 1;
}
fpreg_type = make_node (REAL_TYPE);
/* ??? The back end should know to load/save __fpreg variables using
the ldf.fill and stf.spill instructions. */
- TYPE_PRECISION (fpreg_type) = 96;
+ TYPE_PRECISION (fpreg_type) = 80;
layout_type (fpreg_type);
(*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
/* The __float80 type. */
float80_type = make_node (REAL_TYPE);
- TYPE_PRECISION (float80_type) = 96;
+ TYPE_PRECISION (float80_type) = 80;
layout_type (float80_type);
(*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
(*lang_hooks.types.register_builtin_type) (long_double_type_node,
"__float128");
-#define def_builtin(name, type, code) \
- builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL_TREE)
+#define def_builtin(name, type, code) \
+ lang_hooks.builtin_function ((name), (type), (code), BUILT_IN_MD, \
+ NULL, NULL_TREE)
def_builtin ("__sync_val_compare_and_swap_si", si_ftype_psi_si_si,
IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI);
return gen_rtx_REG (Pmode, GR_REG (8));
}
+static bool
+ia64_scalar_mode_supported_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case QImode:
+ case HImode:
+ case SImode:
+ case DImode:
+ case TImode:
+ return true;
+
+ case SFmode:
+ case DFmode:
+ case XFmode:
+ return true;
+
+ case TFmode:
+ return TARGET_HPUX;
+
+ default:
+ return false;
+ }
+}
+
#include "gt-ia64.h"