diff options
author | Michael Meissner <meissner@gcc.gnu.org> | 1993-06-18 17:36:27 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 1993-06-18 17:36:27 +0000 |
commit | 4bb89a8e5cff5533524ef1e8ea1c790705e17161 (patch) | |
tree | cbe9bdb38b147a2836b41689481da875bdf2a7e1 /gcc | |
parent | aa8642c95d23e9a1c048b995f398ca38c4ddf1c5 (diff) | |
download | gcc-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.c | 30 |
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); |