From 4bb89a8e5cff5533524ef1e8ea1c790705e17161 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Fri, 18 Jun 1993 17:36:27 +0000 Subject: [PATCH] deal with block move input reg also being a scratch reg. From-SVN: r4691 --- gcc/config/mips/mips.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 0e64387918c..20b7a6b62f0 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);