aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Edelsohn <edelsohn@gnu.org>1999-06-19 00:04:59 +0000
committerDavid Edelsohn <dje@gcc.gnu.org>1999-06-18 20:04:59 -0400
commit000034eb46b0c429f01982212bf4879de0fec964 (patch)
treedef29f9c267c1b96504516880ff25f2d567c6a29
parent0b8a1e58d95a80ce908f20a5337080106dd74385 (diff)
downloadgcc-000034eb46b0c429f01982212bf4879de0fec964.zip
gcc-000034eb46b0c429f01982212bf4879de0fec964.tar.gz
gcc-000034eb46b0c429f01982212bf4879de0fec964.tar.bz2
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/rs6000/rs6000.c26
-rw-r--r--gcc/config/rs6000/rs6000.h4
-rw-r--r--gcc/config/rs6000/rs6000.md72
4 files changed, 95 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5efb552..46f9d17 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index d22e4e7..7d6faf5 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 08ac9fd..4e22131 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -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 ();
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index e833863..4286d89 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -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: