aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1993-06-18 17:36:27 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1993-06-18 17:36:27 +0000
commit4bb89a8e5cff5533524ef1e8ea1c790705e17161 (patch)
treecbe9bdb38b147a2836b41689481da875bdf2a7e1 /gcc
parentaa8642c95d23e9a1c048b995f398ca38c4ddf1c5 (diff)
downloadgcc-4bb89a8e5cff5533524ef1e8ea1c790705e17161.zip
gcc-4bb89a8e5cff5533524ef1e8ea1c790705e17161.tar.gz
gcc-4bb89a8e5cff5533524ef1e8ea1c790705e17161.tar.bz2
deal with block move input reg also being a scratch reg.
From-SVN: r4691
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/mips/mips.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 0e64387..20b7a6b 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -2201,6 +2201,7 @@ output_block_move (insn, operands, num_regs, move_type)
int offset = 0;
int use_lwl_lwr = FALSE;
int last_operand = num_regs+4;
+ int safe_regs = 4;
int i;
rtx xoperands[10];
@@ -2215,20 +2216,31 @@ output_block_move (insn, operands, num_regs, move_type)
} load_store[4];
/* Detect a bug in GCC, where it can give us a register
- the same as one of the addressing registers. */
- for (i = 4; i < last_operand; i++)
+ the same as one of the addressing registers and reduce
+ 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])
- || reg_mentioned_p (operands[i], operands[1]))
- {
- abort_with_insn (insn, "register passed as address and temp register to block move");
- }
+ if (!reg_mentioned_p (operands[i], operands[0])
+ && !reg_mentioned_p (operands[i], operands[1]))
+
+ 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
emitting a few instructions, try to save time by using a
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))
{
@@ -2263,7 +2275,7 @@ output_block_move (insn, operands, num_regs, move_type)
num_regs = (sizeof (load_store) / sizeof (load_store[0]));
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)
output_asm_insn (".set\tnoreorder", operands);