deal with block move input reg also being a scratch reg.
From-SVN: r4691
This commit is contained in:
parent
aa8642c95d
commit
4bb89a8e5c
|
@ -2201,6 +2201,7 @@ output_block_move (insn, operands, num_regs, move_type)
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int use_lwl_lwr = FALSE;
|
int use_lwl_lwr = FALSE;
|
||||||
int last_operand = num_regs+4;
|
int last_operand = num_regs+4;
|
||||||
|
int safe_regs = 4;
|
||||||
int i;
|
int i;
|
||||||
rtx xoperands[10];
|
rtx xoperands[10];
|
||||||
|
|
||||||
|
@ -2215,20 +2216,31 @@ output_block_move (insn, operands, num_regs, move_type)
|
||||||
} load_store[4];
|
} load_store[4];
|
||||||
|
|
||||||
/* Detect a bug in GCC, where it can give us a register
|
/* Detect a bug in GCC, where it can give us a register
|
||||||
the same as one of the addressing registers. */
|
the same as one of the addressing registers and reduce
|
||||||
for (i = 4; i < last_operand; i++)
|
the number of registers available. */
|
||||||
|
for (i = 4;
|
||||||
|
i < last_operand && safe_regs < (sizeof(xoperands) / sizeof(xoperands[0]));
|
||||||
|
i++)
|
||||||
{
|
{
|
||||||
if (reg_mentioned_p (operands[i], operands[0])
|
if (!reg_mentioned_p (operands[i], operands[0])
|
||||||
|| reg_mentioned_p (operands[i], operands[1]))
|
&& !reg_mentioned_p (operands[i], operands[1]))
|
||||||
{
|
|
||||||
abort_with_insn (insn, "register passed as address and temp register to block move");
|
xoperands[safe_regs++] = operands[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (safe_regs < last_operand)
|
||||||
|
{
|
||||||
|
xoperands[0] = operands[0];
|
||||||
|
xoperands[1] = operands[1];
|
||||||
|
xoperands[2] = operands[2];
|
||||||
|
xoperands[3] = operands[3];
|
||||||
|
return output_block_move (insn, xoperands, safe_regs-4, move_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are given global or static addresses, and we would be
|
/* If we are given global or static addresses, and we would be
|
||||||
emitting a few instructions, try to save time by using a
|
emitting a few instructions, try to save time by using a
|
||||||
temporary register for the pointer. */
|
temporary register for the pointer. */
|
||||||
if (bytes > 2*align || move_type != BLOCK_MOVE_NORMAL)
|
if (num_regs > 2 && (bytes > 2*align || move_type != BLOCK_MOVE_NORMAL))
|
||||||
{
|
{
|
||||||
if (CONSTANT_P (src_reg))
|
if (CONSTANT_P (src_reg))
|
||||||
{
|
{
|
||||||
|
@ -2263,7 +2275,7 @@ output_block_move (insn, operands, num_regs, move_type)
|
||||||
num_regs = (sizeof (load_store) / sizeof (load_store[0]));
|
num_regs = (sizeof (load_store) / sizeof (load_store[0]));
|
||||||
|
|
||||||
else if (num_regs < 1)
|
else if (num_regs < 1)
|
||||||
abort ();
|
abort_with_insn (insn, "Cannot do block move, not enough scratch registers");
|
||||||
|
|
||||||
if (TARGET_GAS && move_type != BLOCK_MOVE_LAST && set_noreorder++ == 0)
|
if (TARGET_GAS && move_type != BLOCK_MOVE_LAST && set_noreorder++ == 0)
|
||||||
output_asm_insn (".set\tnoreorder", operands);
|
output_asm_insn (".set\tnoreorder", operands);
|
||||||
|
|
Loading…
Reference in New Issue