* config/rs6000/rs6000.c (altivec_in_gprs_p): Rename to ...
(gpr_or_gpr_p): Change to bool.
(rs6000_split_altivec_in_gprs): Rename to ...
(rs6000_split_multireg_move): Add support for update addressing.
* config/rs6000/rs6000-protos.h: Same.
* config/rs6000/altivec.md: Same.
* config/rs6000/rs6000.md (movdi_internal32): Use new splitter for
multiple GPRs.
(movti): Remove TARGET_STRING || TARGET_POWERPC64 final condition.
(movti_power): Use new splitter for multiple GPRs.
(movti_string): Same.
(movti_ppc64): Same.
Co-Authored-By: Hartmut Penner <hpenner@de.ibm.com>
From-SVN: r71673
+2003-09-22 David Edelsohn <edelsohn@gnu.org>
+ Hartmut Penner <hpenner@de.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_in_gprs_p): Rename to ...
+ (gpr_or_gpr_p): Change to bool.
+ (rs6000_split_altivec_in_gprs): Rename to ...
+ (rs6000_split_multireg_move): Add support for update addressing.
+ * config/rs6000/rs6000-protos.h: Same.
+ * config/rs6000/altivec.md: Same.
+ * config/rs6000/rs6000.md (movdi_internal32): Use new splitter for
+ multiple GPRs.
+ (movti): Remove TARGET_STRING || TARGET_POWERPC64 final condition.
+ (movti_power): Use new splitter for multiple GPRs.
+ (movti_string): Same.
+ (movti_ppc64): Same.
+
2003-09-22 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa-protos.h: Convert to ISO C90.
[(set (match_operand:V4SI 0 "nonimmediate_operand" "")
(match_operand:V4SI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
- && altivec_in_gprs_p (operands[0], operands[1])"
+ && gpr_or_gpr_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"{
- rs6000_split_altivec_in_gprs (operands);
+ rs6000_split_multireg_move (operands);
}")
(define_split
[(set (match_operand:V4SI 0 "nonimmediate_operand" "")
(match_operand:V4SI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
- && altivec_in_gprs_p (operands[0], operands[1])"
+ && gpr_or_gpr_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 6))
(set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))]
"{
- rs6000_split_altivec_in_gprs (operands);
+ rs6000_split_multireg_move (operands);
}")
(define_split
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
(match_operand:V8HI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
- && altivec_in_gprs_p (operands[0], operands[1])"
+ && gpr_or_gpr_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"{
- rs6000_split_altivec_in_gprs (operands);
+ rs6000_split_multireg_move (operands);
}")
(define_split
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
(match_operand:V8HI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
- && altivec_in_gprs_p (operands[0], operands[1])"
+ && gpr_or_gpr_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 6))
(set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))]
"{
- rs6000_split_altivec_in_gprs (operands);
+ rs6000_split_multireg_move (operands);
}")
(define_split
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
(match_operand:V16QI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
- && altivec_in_gprs_p (operands[0], operands[1])"
+ && gpr_or_gpr_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"{
- rs6000_split_altivec_in_gprs (operands);
+ rs6000_split_multireg_move (operands);
}")
(define_split
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
(match_operand:V16QI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
- && altivec_in_gprs_p (operands[0], operands[1])"
+ && gpr_or_gpr_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 6))
(set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))]
"{
- rs6000_split_altivec_in_gprs (operands);
+ rs6000_split_multireg_move (operands);
}")
(define_split
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
(match_operand:V4SF 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
- && altivec_in_gprs_p (operands[0], operands[1])"
+ && gpr_or_gpr_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"{
- rs6000_split_altivec_in_gprs (operands);
+ rs6000_split_multireg_move (operands);
}")
(define_split
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
(match_operand:V4SF 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
- && altivec_in_gprs_p (operands[0], operands[1])"
+ && gpr_or_gpr_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 6))
(set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))]
"{
- rs6000_split_altivec_in_gprs (operands);
+ rs6000_split_multireg_move (operands);
}")
(define_insn "get_vrsave_internal"
extern int includes_rldicr_lshift_p (rtx, rtx);
extern int registers_ok_for_quad_peep (rtx, rtx);
extern int addrs_ok_for_quad_peep (rtx, rtx);
-extern int altivec_in_gprs_p (rtx, rtx);
+extern bool gpr_or_gpr_p (rtx, rtx);
extern enum reg_class secondary_reload_class (enum reg_class,
- enum machine_mode, rtx);
+ enum machine_mode, rtx);
extern int ccr_bit (rtx, int);
extern int extract_MB (rtx);
extern int extract_ME (rtx);
extern void print_operand (FILE *, rtx, int);
extern void print_operand_address (FILE *, rtx);
extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
- enum rtx_code);
+ enum rtx_code);
extern void rs6000_emit_sCOND (enum rtx_code, rtx);
extern void rs6000_emit_cbranch (enum rtx_code, rtx);
extern char * output_cbranch (rtx, const char *, int, rtx);
extern int mtcrf_operation (rtx, enum machine_mode);
extern int lmw_operation (rtx, enum machine_mode);
extern struct rtx_def *create_TOC_reference (rtx);
-extern void rs6000_split_altivec_in_gprs (rtx *);
+extern void rs6000_split_multireg_move (rtx *);
extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
#endif
}
-/* Return 1 for all valid move insn operand combination involving altivec
- vectors in gprs. */
+/* Return true if either operand is a general purpose register. */
-int
-altivec_in_gprs_p (rtx op0, rtx op1)
+bool
+gpr_or_gpr_p (rtx op0, rtx op1)
{
- if (REG_P (op0) && REGNO_REG_CLASS (REGNO (op0)) == GENERAL_REGS)
- return 1;
-
- if (REG_P (op1) && REGNO_REG_CLASS (REGNO (op1)) == GENERAL_REGS)
- return 1;
- return 0;
+ return ((REG_P (op0) && INT_REGNO_P (REGNO (op0)))
+ || (REG_P (op1) && INT_REGNO_P (REGNO (op1))));
}
\f
emit_move_insn (dest, target);
}
-/* Called by altivec splitter.
+/* Called by splitter for multireg moves.
Input:
operands[0] : Destination of move
operands[1] : Source of move
- noperands : Size of operands vector
+
Output:
- operands[2-5] ([2-3] in 64 bit) : Destination slots
- operands[6-9] ([4-5] in 64 bit) : Source slots
+ operands[2-n] : Destination slots
+ operands[n-m] : Source slots
+ where n = 2 + HARD_REGNO_NREGS (reg, GET_MODE (operands[0]))
+ m = 2 + 2 * HARD_REGNO_NREGS (reg, GET_MODE (operands[0])) - 1
Splits the move of operands[1] to operands[0].
This is done, if GPRs are one of the operands. In this case
*/
void
-rs6000_split_altivec_in_gprs (rtx *operands)
+rs6000_split_multireg_move (rtx *operands)
{
- int nregs, reg, i, j;
+ int nregs, reg, i, j, used_update = 0;
enum machine_mode mode;
+ rtx dst = operands[0];
+ rtx src = operands[1];
+ rtx insn = 0;
/* Calculate number to move (2/4 for 32/64 bit mode). */
for (i = 0; i < nregs; i++)
{
j--;
- operands[i + 2] = operand_subword (operands[0], j, 0, mode);
- operands[i + 2 + nregs] =
+ operands[i+2] = operand_subword (operands[0], j, 0, mode);
+ operands[i+2+nregs] =
operand_subword (operands[1], j, 0, mode);
}
}
if (GET_CODE (operands[1]) == MEM)
{
rtx breg;
- /* We have offsettable addresses only. If we use one of the
- registers to address memory, we have change that register last. */
- breg = GET_CODE (XEXP (operands[1], 0)) == PLUS ?
- XEXP (XEXP (operands[1], 0), 0) :
- XEXP (operands[1], 0);
-
- if (REGNO (breg) >= REGNO (operands[0])
- && REGNO (breg) < REGNO (operands[0]) + nregs)
- j = REGNO (breg) - REGNO (operands[0]);
+
+ if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
+ || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+ {
+ rtx delta_rtx;
+ breg = XEXP (XEXP (operands[1], 0), 0);
+ delta_rtx = GET_CODE (XEXP (operands[1], 0)) == PRE_INC
+ ? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])))
+ : GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[1])));
+ insn = emit_insn (TARGET_32BIT
+ ? gen_addsi3 (breg, breg, delta_rtx)
+ : gen_adddi3 (breg, breg, delta_rtx));
+ src = gen_rtx_MEM (mode, breg);
+ }
+
+ /* We have now address involving an base register only.
+ If we use one of the registers to address memory,
+ we have change that register last. */
+
+ breg = (GET_CODE (XEXP (src, 0)) == PLUS
+ ? XEXP (XEXP (src, 0), 0)
+ : XEXP (src, 0));
+
+ if (!REG_P (breg))
+ abort();
+
+ if (REGNO (breg) >= REGNO (dst)
+ && REGNO (breg) < REGNO (dst) + nregs)
+ j = REGNO (breg) - REGNO (dst);
}
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ rtx breg;
+
+ if (GET_CODE (XEXP (operands[0], 0)) == PRE_INC
+ || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ rtx delta_rtx;
+ breg = XEXP (XEXP (operands[0], 0), 0);
+ delta_rtx = GET_CODE (XEXP (operands[0], 0)) == PRE_INC
+ ? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])))
+ : GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0])));
+
+ /* We have to update the breg before doing the store.
+ Use store with update, if available. */
+
+ if (TARGET_UPDATE)
+ {
+ insn = emit_insn (TARGET_32BIT
+ ? gen_movsi_update (breg, breg, delta_rtx,
+ operand_subword (src, 0, 0, mode))
+ : gen_movdi_update (breg, breg, delta_rtx,
+ operand_subword (src, 0, 0, mode)));
+ used_update = 1;
+ }
+ else
+ insn = emit_insn (TARGET_32BIT
+ ? gen_addsi3 (breg, breg, delta_rtx)
+ : gen_adddi3 (breg, breg, delta_rtx));
+ dst = gen_rtx_MEM (mode, breg);
+ }
+ }
+
for (i = 0; i < nregs; i++)
- {
- /* Calculate index to next subword. */
- j++;
- if (j == nregs)
- j = 0;
+ {
+ /* Calculate index to next subword. */
+ ++j;
+ if (j == nregs)
+ j = 0;
- operands[i + 2] = operand_subword (operands[0], j, 0, mode);
- operands[i + 2 + nregs] =
- operand_subword (operands[1], j, 0, mode);
+ operands[i+2] = operand_subword (dst, j, 0, mode);
+ operands[i+2+nregs] = operand_subword (src, j, 0, mode);
- }
+ if (j == 0 && used_update)
+ {
+ /* Already emited move of first word by
+ store with update -> emit dead insn instead (r := r). */
+ operands[i+2] = operands[i+2+nregs];
+ }
+ }
}
}
default:
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. */
- 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\";
- else
- return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
case 2:
- return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
+ return \"#\";
case 3:
return \"fmr %0,%1\";
case 4:
return \"#\";
}
}"
- [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")
- (set_attr "length" "8,8,8,4,4,4,8,12,8,12,16")])
+ [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
}")
+(define_split
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (match_operand:DI 1 "input_operand" ""))]
+ "reload_completed && !TARGET_POWERPC64
+ && gpr_or_gpr_p (operands[0], operands[1])"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+"{
+ rs6000_split_multireg_move (operands);
+}")
+
(define_split
[(set (match_operand:TI 0 "gpc_reg_operand" "")
(match_operand:TI 1 "const_double_operand" ""))]
[(parallel [(set (match_operand:TI 0 "general_operand" "")
(match_operand:TI 1 "general_operand" ""))
(clobber (scratch:SI))])]
- "TARGET_STRING || TARGET_POWERPC64"
+ ""
"{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }")
;; We say that MQ is clobbered in the last alternative because the first
;; while the 2nd alternative would not. We put memory cases first so they
;; are preferred. Otherwise, we'd try to reload the output instead of
;; giving the SCRATCH mq.
+
(define_insn "*movti_power"
[(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
(match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
(clobber (match_scratch:SI 2 "=q,q#X,X,X,X"))]
- "TARGET_STRING && TARGET_POWER && ! TARGET_POWERPC64
+ "TARGET_POWER && ! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
"*
{
abort ();
case 0:
- return \"{stsi|stswi} %1,%P0,16\";
+ if (TARGET_STRING)
+ return \"{stsi|stswi} %1,%P0,16\";
case 1:
- return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\";
+ return \"#\";
case 2:
- /* Normally copy registers with lowest numbered register copied first.
- But copy in the other order if the first register of the output
- is the second, third, or fourth register in the input. */
- if (REGNO (operands[0]) >= REGNO (operands[1]) + 1
- && REGNO (operands[0]) <= REGNO (operands[1]) + 3)
- return \"mr %Z0,%Z1\;mr %Y0,%Y1\;mr %L0,%L1\;mr %0,%1\";
- else
- return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ return \"#\";
case 3:
/* If the address is not used in the output, we can use lsi. Otherwise,
fall through to generating four loads. */
return \"{lsi|lswi} %0,%P1,16\";
/* ... fall through ... */
case 4:
- /* If the address register is the same as the register for the lowest-
- addressed word, load it last. Similarly for the next two words.
- Otherwise load lowest address to highest. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], 0))
- return \"{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %0,%1\";
- else if (refers_to_regno_p (REGNO (operands[0]) + 1,
- REGNO (operands[0]) + 2, operands[1], 0))
- return \"{l|lwz} %0,%1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %L0,%L1\";
- else if (refers_to_regno_p (REGNO (operands[0]) + 2,
- REGNO (operands[0]) + 3, operands[1], 0))
- return \"{l|lwz} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Z0,%Z1\;{l|lwz} %Y0,%Y1\";
- else
- return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\";
+ return \"#\";
}
}"
- [(set_attr "type" "store,store,*,load,load")
- (set_attr "length" "4,16,16,4,16")])
+ [(set_attr "type" "store,store,*,load,load")])
(define_insn "*movti_string"
[(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
(match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))]
- "TARGET_STRING && ! TARGET_POWER && ! TARGET_POWERPC64
+ "! TARGET_POWER && ! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
"*
{
{
default:
abort ();
-
case 0:
- return \"{stsi|stswi} %1,%P0,16\";
+ if (TARGET_STRING)
+ return \"{stsi|stswi} %1,%P0,16\";
case 1:
- return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\";
+ return \"#\";
case 2:
- /* Normally copy registers with lowest numbered register copied first.
- But copy in the other order if the first register of the output
- is the second, third, or fourth register in the input. */
- if (REGNO (operands[0]) >= REGNO (operands[1]) + 1
- && REGNO (operands[0]) <= REGNO (operands[1]) + 3)
- return \"mr %Z0,%Z1\;mr %Y0,%Y1\;mr %L0,%L1\;mr %0,%1\";
- else
- return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ return \"#\";
case 3:
/* If the address is not used in the output, we can use lsi. Otherwise,
fall through to generating four loads. */
- if (! reg_overlap_mentioned_p (operands[0], operands[1]))
+ if (TARGET_STRING
+ && ! reg_overlap_mentioned_p (operands[0], operands[1]))
return \"{lsi|lswi} %0,%P1,16\";
/* ... fall through ... */
case 4:
- /* If the address register is the same as the register for the lowest-
- addressed word, load it last. Similarly for the next two words.
- Otherwise load lowest address to highest. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], 0))
- return \"{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %0,%1\";
- else if (refers_to_regno_p (REGNO (operands[0]) + 1,
- REGNO (operands[0]) + 2, operands[1], 0))
- return \"{l|lwz} %0,%1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %L0,%L1\";
- else if (refers_to_regno_p (REGNO (operands[0]) + 2,
- REGNO (operands[0]) + 3, operands[1], 0))
- return \"{l|lwz} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Z0,%Z1\;{l|lwz} %Y0,%Y1\";
- else
- return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\";
+ return \"#\";
}
}"
- [(set_attr "type" "store,store,*,load,load")
- (set_attr "length" "4,16,16,4,16")])
+ [(set_attr "type" "store,store,*,load,load")])
(define_insn "*movti_ppc64"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:TI 1 "input_operand" "r,m,r"))]
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r,m,r")
+ (match_operand:TI 1 "input_operand" "r,r,o"))]
"TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
|| gpc_reg_operand (operands[1], TImode))"
- "*
-{
- switch (which_alternative)
- {
- default:
- 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. */
- 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 \"ld %L0,%L1\;ld %0,%1\";
- else
- return \"ld%U1 %0,%1\;ld %L0,%L1\";
- case 2:
- return \"std%U0 %1,%0\;std %L1,%L0\";
- }
-}"
- [(set_attr "type" "*,load,store")
- (set_attr "length" "8,8,8")])
+ "@
+ #
+ #
+ #"
+ [(set_attr "type" "*,load,store")])
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "input_operand" ""))]
+ "reload_completed && TARGET_POWERPC64
+ && gpr_or_gpr_p (operands[0], operands[1])"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+"{
+ rs6000_split_multireg_move (operands);
+}")
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "input_operand" ""))]
+ "reload_completed && !TARGET_POWERPC64
+ && gpr_or_gpr_p (operands[0], operands[1])"
+ [(set (match_dup 2) (match_dup 6))
+ (set (match_dup 3) (match_dup 7))
+ (set (match_dup 4) (match_dup 8))
+ (set (match_dup 5) (match_dup 9))]
+"{
+ rs6000_split_multireg_move (operands);
+}")
+
+
\f
(define_expand "load_multiple"
[(match_par_dup 3 [(set (match_operand:SI 0 "" "")