/* Place that this stack area has been saved, if needed. */
rtx save_area;
#endif
+#ifdef STRICT_ALIGNMENT
+ /* If an argument's alignment does not permit direct copying into registers,
+ copy in smaller-sized pieces into pseudos. These are stored in a
+ block pointed to by this field. The next field says how many
+ word-sized pseudos we made. */
+ rtx *aligned_regs;
+ int n_aligned_regs;
+#endif
};
#ifdef ACCUMULATE_OUTGOING_ARGS
rtx use_insns = 0;
register tree p;
- register int i;
+ register int i, j;
/* See if we can find a DECL-node for the actual function.
As a result, decide whether this is a call to an integrable function. */
/* If inlining succeeded, return. */
if ((HOST_WIDE_INT) temp != -1)
{
- int i;
-
/* Perform all cleanups needed for the arguments of this call
(i.e. destructors in C++). It is ok if these destructors
clobber RETURN_VALUE_REG, because the only time we care about
store_one_arg (&args[i], argblock, may_be_alloca,
args_size.var != 0, fndecl, reg_parm_stack_space);
+#ifdef STRICT_ALIGNMENT
+ /* If we have a parm that is passed in registers but not in memory
+ and whose alignment does not permit a direct copy into registers,
+ make a group of pseudos that correspond to each register that we
+ will later fill. */
+
+ for (i = 0; i < num_actuals; i++)
+ if (args[i].reg != 0 && ! args[i].pass_on_stack
+ && args[i].mode == BLKmode
+ && (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
+ < MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
+ {
+ int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
+
+ args[i].n_aligned_regs
+ = args[i].partial ? args[i].partial
+ : (bytes + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
+
+ args[i].aligned_regs = (rtx *) alloca (sizeof (rtx)
+ * args[i].n_aligned_regs);
+
+ for (j = 0; j < args[i].n_aligned_regs; j++)
+ {
+ rtx reg = gen_reg_rtx (word_mode);
+ rtx word = operand_subword_force (args[i].value, j, BLKmode);
+ int bitsize = TYPE_ALIGN (TREE_TYPE (args[i].tree_value));
+ int bitpos;
+
+ args[i].aligned_regs[j] = reg;
+
+ /* Clobber REG and move each partword into it. Ensure we don't
+ go past the end of the structure. Note that the loop below
+ works because we've already verified that padding
+ and endianness are compatible. */
+
+ emit_insn (gen_rtx (CLOBBER, VOIDmode, reg));
+
+ for (bitpos = 0;
+ bitpos < BITS_PER_WORD && bytes >= 0;
+ bitpos += bitsize, bytes -= bitsize / BITS_PER_UNIT)
+ {
+ int xbitpos = (BYTES_BIG_ENDIAN
+ ? bitpos = BITS_PER_WORD - bitpos - bitsize
+ : bitpos);
+
+ store_bit_field (reg, bitsize, xbitpos, word_mode,
+ extract_bit_field (word, bitsize, xbitpos, 1,
+ NULL_RTX, word_mode,
+ word_mode,
+ bitsize / BITS_PER_UNIT,
+ BITS_PER_WORD),
+ bitsize / BITS_PER_UNIT, BITS_PER_WORD);
+ }
+ }
+ }
+#endif
+
/* Now store any partially-in-registers parm.
This is the last place a block-move can happen. */
if (reg_parm_seen)
if (nregs == 0)
emit_move_insn (reg, args[i].value);
+
+#ifdef STRICT_ALIGNMENT
+ /* If we have pre-computed the values to put in the registers in
+ the case of non-aligned structures, copy them in now. */
+
+ else if (args[i].n_aligned_regs != 0)
+ for (j = 0; j < args[i].n_aligned_regs; j++)
+ emit_move_insn (gen_rtx (REG, word_mode, REGNO (reg) + j),
+ args[i].aligned_regs[j]);
+#endif
+
else if (args[i].partial == 0 || args[i].pass_on_stack)
move_block_to_reg (REGNO (reg),
validize_mem (args[i].value), nregs,
this case. */
abort ();
+#ifdef STRICT_ALIGNMENT
+ /* If this arg needs special alignment, don't load the registers
+ here. */
+ if (arg->n_aligned_regs != 0)
+ reg = 0;
+#endif
+
/* If this is being partially passed in a register, but multiple locations
are specified, we assume that the one partially used is the one that is
listed first. */
if (reg && GET_CODE (reg) == EXPR_LIST)
reg = XEXP (reg, 0);
- /* If this is being passes partially in a register, we can't evaluate
+ /* If this is being passed partially in a register, we can't evaluate
it directly into its stack slot. Otherwise, we can. */
if (arg->value == 0)
{