rs6000.c (find_addr_reg): New function.

* rs6000.c (find_addr_reg): New function.
        * rs6000.h (find_addr_reg): Declare.
        (offsettable_addr_operand): Delete.
        * rs6000.md (movdf_hardfloat32): Handle non-offsettable loads
        from and stores to GPRs.

From-SVN: r27602
This commit is contained in:
David Edelsohn 1999-06-19 00:04:59 +00:00 committed by David Edelsohn
parent 0b8a1e58d9
commit 000034eb46
4 changed files with 95 additions and 15 deletions

View File

@ -1,3 +1,11 @@
Fri Jun 18 23:47:06 1999 David Edelsohn <edelsohn@gnu.org>
* rs6000.c (find_addr_reg): New function.
* rs6000.h (find_addr_reg): Declare.
(offsettable_addr_operand): Delete.
* rs6000.md (movdf_hardfloat32): Handle non-offsettable loads
from and stores to GPRs.
Fri Jun 18 15:44:18 1999 Richard Henderson <rth@cygnus.com>
* alpha.c (alpha_expand_block_move): Use get_insns rather than

View File

@ -5681,7 +5681,33 @@ rs6000_encode_section_info (decl)
}
#endif /* USING_SVR4_H */
/* Return a REG that occurs in ADDR with coefficient 1.
ADDR can be effectively incremented by incrementing REG. */
struct rtx_def *
find_addr_reg (addr)
rtx addr;
{
while (GET_CODE (addr) == PLUS)
{
if (GET_CODE (XEXP (addr, 0)) == REG)
addr = XEXP (addr, 0);
else if (GET_CODE (XEXP (addr, 1)) == REG)
addr = XEXP (addr, 1);
else if (CONSTANT_P (XEXP (addr, 0)))
addr = XEXP (addr, 1);
else if (CONSTANT_P (XEXP (addr, 1)))
addr = XEXP (addr, 0);
else
abort ();
}
if (GET_CODE (addr) == REG)
return addr;
abort ();
}
void
rs6000_fatal_bad_address (op)
rtx op;

View File

@ -3224,13 +3224,13 @@ extern int flag_expensive_optimizations;
extern int frame_pointer_needed;
/* Declare functions in rs6000.c */
extern int offsettable_mem_operand ();
extern void optimization_options ();
extern void output_options ();
extern void rs6000_override_options ();
extern void rs6000_file_start ();
extern struct rtx_def *rs6000_float_const ();
extern struct rtx_def *rs6000_got_register ();
extern struct rtx_def *find_addr_reg();
extern int direct_return ();
extern int get_issue_rate ();
extern int any_operand ();
@ -3249,7 +3249,7 @@ extern int got_no_const_operand ();
extern int num_insns_constant ();
extern int easy_fp_constant ();
extern int volatile_mem_operand ();
extern int offsettable_addr_operand ();
extern int offsettable_mem_operand ();
extern int mem_or_easy_const_operand ();
extern int add_operand ();
extern int non_add_cint_operand ();

View File

@ -6307,8 +6307,8 @@
;; The "??" is a kludge until we can figure out a more reasonable way
;; of handling these non-offsettable values.
(define_insn "*movdf_hardfloat32"
[(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,!r,!r,f,f,m")
(match_operand:DF 1 "input_operand" "r,o,r,G,H,F,f,m,f"))]
[(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,!r,!r,!r,f,f,m")
(match_operand:DF 1 "input_operand" "r,m,r,G,H,F,f,m,f"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
@ -6320,24 +6320,70 @@
abort ();
case 0:
/* We normally copy the low-numbered register first. However, if
the first register operand 0 is the same as the second register of
operand 1, we must copy in the opposite order. */
the first register operand 0 is the same as the second register
of operand 1, we must copy in the opposite order. */
if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
return \"mr %L0,%L1\;mr %0,%1\";
else
return \"mr %0,%1\;mr %L0,%L1\";
case 1:
/* If the low-address word is used in the address, we must load it
last. Otherwise, load it first. Note that we cannot have
auto-increment in that case since the address register is known to be
dead. */
if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
operands [1], 0))
return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
if (offsettable_memref_p (operands[1]))
{
/* If the low-address word is used in the address, we must load
it last. Otherwise, load it first. Note that we cannot have
auto-increment in that case since the address register is
known to be dead. */
if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
operands[1], 0))
return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
else
return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
}
else
return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
{
rtx addreg;
if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
|| GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
abort ();
addreg = find_addr_reg (XEXP (operands[1], 0));
if (refers_to_regno_p (REGNO (operands[0]),
REGNO (operands[0]) + 1,
operands[1], 0))
{
output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
return \"{lx|lwzx} %0,%1\";
}
else
{
output_asm_insn (\"{lx|lwzx} %0,%1\", operands);
output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
return \"\";
}
}
case 2:
return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
if (offsettable_memref_p (operands[0]))
return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
else
{
rtx addreg;
if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
|| GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
abort ();
addreg = find_addr_reg (XEXP (operands[0], 0));
output_asm_insn (\"{stx|stwx} %1,%0\", operands);
output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
output_asm_insn (\"{stx|stwx} %L1,%0\", operands);
output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
return \"\";
}
case 3:
case 4:
case 5: