Commit fffa9c1d by Jim Wilson

(emit_group_load, emit_group_store): New functions.

(use_group_regs): New function.
(emit_push_insn): Handle PARALLEL parameter in REG.
(expand_assignment): Handle PARALLEL to_rtx.
(store_expr): Handle PARALLEL target.

From-SVN: r12189
parent cacbd532
...@@ -1817,6 +1817,92 @@ move_block_from_reg (regno, x, nregs, size) ...@@ -1817,6 +1817,92 @@ move_block_from_reg (regno, x, nregs, size)
} }
} }
/* Emit code to move a block Y to a block X, where X is non-consecutive
registers represented by a PARALLEL. */
void
emit_group_load (x, y)
rtx x, y;
{
rtx target_reg, source;
int i;
if (GET_CODE (x) != PARALLEL)
abort ();
/* Check for a NULL entry, used to indicate that the parameter goes
both on the stack and in registers. */
if (XEXP (XVECEXP (x, 0, 0), 0))
i = 0;
else
i = 1;
for (; i < XVECLEN (x, 0); i++)
{
rtx element = XVECEXP (x, 0, i);
target_reg = XEXP (element, 0);
if (GET_CODE (y) == MEM)
source = change_address (y, GET_MODE (target_reg),
plus_constant (XEXP (y, 0),
INTVAL (XEXP (element, 1))));
else if (XEXP (element, 1) == const0_rtx)
{
if (GET_MODE (target_reg) == GET_MODE (y))
source = y;
else if (GET_MODE_SIZE (GET_MODE (target_reg))
== GET_MODE_SIZE (GET_MODE (y)))
source = gen_rtx (SUBREG, GET_MODE (target_reg), y, 0);
else
abort ();
}
else
abort ();
emit_move_insn (target_reg, source);
}
}
/* Emit code to move a block Y to a block X, where Y is non-consecutive
registers represented by a PARALLEL. */
void
emit_group_store (x, y)
rtx x, y;
{
rtx source_reg, target;
int i;
if (GET_CODE (y) != PARALLEL)
abort ();
/* Check for a NULL entry, used to indicate that the parameter goes
both on the stack and in registers. */
if (XEXP (XVECEXP (y, 0, 0), 0))
i = 0;
else
i = 1;
for (; i < XVECLEN (y, 0); i++)
{
rtx element = XVECEXP (y, 0, i);
source_reg = XEXP (element, 0);
if (GET_CODE (x) == MEM)
target = change_address (x, GET_MODE (source_reg),
plus_constant (XEXP (x, 0),
INTVAL (XEXP (element, 1))));
else if (XEXP (element, 1) == const0_rtx)
target = x;
else
abort ();
emit_move_insn (target, source_reg);
}
}
/* Add a USE expression for REG to the (possibly empty) list pointed /* Add a USE expression for REG to the (possibly empty) list pointed
to by CALL_FUSAGE. REG must denote a hard register. */ to by CALL_FUSAGE. REG must denote a hard register. */
...@@ -1850,6 +1936,28 @@ use_regs (call_fusage, regno, nregs) ...@@ -1850,6 +1936,28 @@ use_regs (call_fusage, regno, nregs)
for (i = 0; i < nregs; i++) for (i = 0; i < nregs; i++)
use_reg (call_fusage, gen_rtx (REG, reg_raw_mode[regno + i], regno + i)); use_reg (call_fusage, gen_rtx (REG, reg_raw_mode[regno + i], regno + i));
} }
/* Add USE expressions to *CALL_FUSAGE for each REG contained in the
PARALLEL REGS. This is for calls that pass values in multiple
non-contiguous locations. The Irix 6 ABI has examples of this. */
void
use_group_regs (call_fusage, regs)
rtx *call_fusage;
rtx regs;
{
int i;
/* Check for a NULL entry, used to indicate that the parameter goes
both on the stack and in registers. */
if (XEXP (XVECEXP (regs, 0, 0), 0))
i = 0;
else
i = 1;
for (; i < XVECLEN (regs, 0); i++)
use_reg (call_fusage, XEXP (XVECEXP (regs, 0, i), 0));
}
/* Generate several move instructions to clear LEN bytes of block TO. /* Generate several move instructions to clear LEN bytes of block TO.
(A MEM rtx with BLKmode). The caller must pass TO through (A MEM rtx with BLKmode). The caller must pass TO through
...@@ -2648,7 +2756,14 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, ...@@ -2648,7 +2756,14 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
into the appropriate registers. Do this now, at the end, into the appropriate registers. Do this now, at the end,
since mem-to-mem copies above may do function calls. */ since mem-to-mem copies above may do function calls. */
if (partial > 0 && reg != 0) if (partial > 0 && reg != 0)
move_block_to_reg (REGNO (reg), x, partial, mode); {
/* Handle calls that pass values in multiple non-contiguous locations.
The Irix 6 ABI has examples of this. */
if (GET_CODE (reg) == PARALLEL)
emit_group_load (reg, x);
else
move_block_to_reg (REGNO (reg), x, partial, mode);
}
if (extra && args_addr == 0 && where_pad == stack_direction) if (extra && args_addr == 0 && where_pad == stack_direction)
anti_adjust_stack (GEN_INT (extra)); anti_adjust_stack (GEN_INT (extra));
...@@ -2812,7 +2927,11 @@ expand_assignment (to, from, want_value, suggest_reg) ...@@ -2812,7 +2927,11 @@ expand_assignment (to, from, want_value, suggest_reg)
if (to_rtx == 0) if (to_rtx == 0)
to_rtx = expand_expr (to, NULL_RTX, VOIDmode, 0); to_rtx = expand_expr (to, NULL_RTX, VOIDmode, 0);
if (GET_MODE (to_rtx) == BLKmode) /* Handle calls that return values in multiple non-contiguous locations.
The Irix 6 ABI has examples of this. */
if (GET_CODE (to_rtx) == PARALLEL)
emit_group_load (to_rtx, value);
else if (GET_MODE (to_rtx) == BLKmode)
emit_block_move (to_rtx, value, expr_size (from), emit_block_move (to_rtx, value, expr_size (from),
TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT); TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
else else
...@@ -3167,6 +3286,10 @@ store_expr (exp, target, want_value) ...@@ -3167,6 +3286,10 @@ store_expr (exp, target, want_value)
emit_label (label); emit_label (label);
} }
} }
/* Handle calls that return values in multiple non-contiguous locations.
The Irix 6 ABI has examples of this. */
else if (GET_CODE (target) == PARALLEL)
emit_group_load (target, temp);
else if (GET_MODE (temp) == BLKmode) else if (GET_MODE (temp) == BLKmode)
emit_block_move (target, temp, expr_size (exp), emit_block_move (target, temp, expr_size (exp),
TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment