char toc_label_name[10];
/* Alias set for saves and restores from the rs6000 stack. */
-static int rs6000_sr_alias_set;
+static GTY(()) int rs6000_sr_alias_set;
/* Call distance, overridden by -mlongcall and #pragma longcall(1).
The only place that looks at this is rs6000_set_default_type_attributes;
return 0;
}
+
+/* Darwin, AIX increases natural record alignment to doubleword if the first
+ field is an FP double while the FP fields remain word aligned. */
+
+unsigned int
+rs6000_special_round_type_align (tree type, int computed, int specified)
+{
+ tree field = TYPE_FIELDS (type);
+
+ /* Skip all the static variables only if ABI is greater than
+ 1 or equal to 0. */
+ while (field != NULL && TREE_CODE (field) == VAR_DECL)
+ field = TREE_CHAIN (field);
+
+ if (field == NULL || field == type || DECL_MODE (field) != DFmode)
+ return MAX (computed, specified);
+
+ return MAX (MAX (computed, specified), 64);
+}
+
/* Return 1 for an operand in small memory on V.4/eabi. */
int
adjust_address (operands[1], SImode, 4));
return;
}
+#if 0
+ else if (mode == DImode && TARGET_POWERPC64
+ && GET_CODE (operands[0]) == REG
+ && GET_CODE (operands[1]) == MEM && optimize > 0
+ && SLOW_UNALIGNED_ACCESS (DImode,
+ MEM_ALIGN (operands[1]) > 32
+ ? 32
+ : MEM_ALIGN (operands[1]))
+ && !no_new_pseudos)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+ emit_insn (gen_rtx_SET (SImode, reg,
+ adjust_address (operands[1], SImode, 0)));
+ reg = simplify_gen_subreg (DImode, reg, SImode, 0);
+ emit_insn (gen_insvdi (operands[0], GEN_INT (32), const0_rtx, reg));
+ reg = gen_reg_rtx (SImode);
+ emit_insn (gen_rtx_SET (SImode, reg,
+ adjust_address (operands[1], SImode, 4)));
+ reg = simplify_gen_subreg (DImode, reg, SImode, 0);
+ emit_insn (gen_insvdi (operands[0], GEN_INT (32), GEN_INT (32), reg));
+ return;
+ }
+ else if (mode == DImode && TARGET_POWERPC64
+ && GET_CODE (operands[1]) == REG
+ && GET_CODE (operands[0]) == MEM && optimize > 0
+ && SLOW_UNALIGNED_ACCESS (DImode,
+ MEM_ALIGN (operands[0]) > 32
+ ? 32
+ : MEM_ALIGN (operands[0]))
+ && !no_new_pseudos)
+ {
+ rtx reg = gen_reg_rtx (DImode);
+ emit_move_insn (reg,
+ gen_rtx_LSHIFTRT (DImode, operands[1], GEN_INT (32)));
+ emit_move_insn (adjust_address (operands[0], SImode, 0),
+ simplify_gen_subreg (SImode, reg, DImode, 0));
+ emit_move_insn (adjust_address (operands[0], SImode, 4),
+ simplify_gen_subreg (SImode, operands[1], DImode, 0));
+ return;
+ }
+#endif
if (!no_new_pseudos)
{
if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
cum->vregno++;
- /* In variable-argument functions, vector arguments get GPRs allocated
- even if they are going to be passed in a vector register. */
- if (cum->stdarg && DEFAULT_ABI != ABI_V4)
- {
+ /* PowerPC64 Linux and AIX allocates GPRs for a vector argument
+ even if it is going to be passed in a vector register.
+ Darwin does the same for variable-argument functions. */
+ if ((DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
+ || (cum->stdarg && DEFAULT_ABI != ABI_V4))
+ {
int align;
/* Vector parameters must be 16-byte aligned. This places
}
if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
- return gen_rtx_REG (mode, cum->vregno);
+ if (TARGET_64BIT && ! cum->prototype)
+ {
+ /* Vector parameters get passed in vector register
+ and also in GPRs or memory, in absence of prototype. */
+ int align_words;
+ rtx slot;
+ align_words = (cum->words + 1) & ~1;
+
+ if (align_words >= GP_ARG_NUM_REG)
+ {
+ slot = NULL_RTX;
+ }
+ else
+ {
+ slot = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
+ }
+ return gen_rtx_PARALLEL (mode,
+ gen_rtvec (2,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ slot, const0_rtx),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode, cum->vregno),
+ const0_rtx)));
+ }
+ else
+ return gen_rtx_REG (mode, cum->vregno);
else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
{
if (named || abi == ABI_V4)
}
static void
-rs6000_move_block_from_reg(int regno, rtx x, int nregs)
+rs6000_move_block_from_reg (int regno, rtx x, int nregs)
{
int i;
enum machine_mode reg_mode = TARGET_32BIT ? SImode : DImode;
return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
}
else
- {
- /* Altivec arguments must be aligned to a 128-bit boundary. */
- if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
- {
- tree vtype = TREE_TYPE (valist);
- tree new_valist, modify;
-
- /* Round address up to multiple of 16. Computes
- (addr+15)&~0xf. */
- new_valist = fold (build (BIT_AND_EXPR, vtype,
- fold (build (PLUS_EXPR, vtype, valist,
- build_int_2 (15, 0))),
- build_int_2 (~15, -1)));
-
- /* Update valist. */
- modify = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
- new_valist);
- TREE_SIDE_EFFECTS (modify) = 1;
- expand_expr (modify, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
-
- return std_expand_builtin_va_arg (valist, type);
- }
+ return std_expand_builtin_va_arg (valist, type);
}
f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
else
info_ptr->spe_gp_size = 0;
- if (TARGET_ALTIVEC_ABI && TARGET_ALTIVEC_VRSAVE)
- {
- info_ptr->vrsave_mask = compute_vrsave_mask ();
- info_ptr->vrsave_size = info_ptr->vrsave_mask ? 4 : 0;
- }
+ if (TARGET_ALTIVEC_ABI)
+ info_ptr->vrsave_mask = compute_vrsave_mask ();
else
- {
- info_ptr->vrsave_mask = 0;
- info_ptr->vrsave_size = 0;
- }
+ info_ptr->vrsave_mask = 0;
+
+ if (TARGET_ALTIVEC_VRSAVE && info_ptr->vrsave_mask)
+ info_ptr->vrsave_size = 4;
+ else
+ info_ptr->vrsave_size = 0;
/* Calculate the offsets. */
switch (DEFAULT_ABI)
emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]);
}
+static GTY(()) int set = -1;
+
int
get_TOC_alias_set (void)
{
- static int set = -1;
- if (set == -1)
- set = new_alias_set ();
- return set;
+ if (set == -1)
+ set = new_alias_set ();
+ return set;
}
/* This returns nonzero if the current function uses the TOC. This is
- determined by the presence of (unspec ... UNSPEC_TOC) or
- use (unspec ... UNSPEC_TOC), which are generated by the various
- load_toc_* patterns. */
-
-int
+ determined by the presence of (use (unspec ... UNSPEC_TOC)), which
+ is generated by the ABI_V4 load_toc_* patterns. */
+#if TARGET_ELF
+static int
uses_TOC (void)
{
rtx insn;
}
return 0;
}
+#endif
rtx
create_TOC_reference (rtx symbol)
used in this function, and do the corresponding magic in the
epilogue. */
- if (TARGET_ALTIVEC && info->vrsave_mask != 0)
+ if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
+ && info->vrsave_mask != 0)
{
rtx reg, mem, vrsave;
int offset;
}
/* Restore VRSAVE if needed. */
- if (TARGET_ALTIVEC_ABI && info->vrsave_mask != 0)
+ if (TARGET_ALTIVEC_ABI && TARGET_ALTIVEC_VRSAVE
+ && info->vrsave_mask != 0)
{
rtx addr, mem, reg;
if (TARGET_RELOCATABLE
&& (get_pool_size () != 0 || current_function_profile)
- && uses_TOC())
+ && uses_TOC ())
{
char buf[256];