case 0: return \"stvx %1,%y0\";
case 1: return \"lvx %0,%y1\";
case 2: return \"vor %0,%1,%1\";
- case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
- case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
- case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ case 3: return \"#\";
+ case 4: return \"#\";
+ case 5: return \"#\";
case 6: return output_vec_const_move (operands);
default: abort();
}
}"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
- (set_attr "length" "*,*,*,16,16,16,*")])
+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+
+(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])"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+"{
+ rs6000_split_altivec_in_gprs (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])"
+ [(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);
+}")
(define_split
[(set (match_operand:V4SI 0 "altivec_register_operand" "")
case 0: return \"stvx %1,%y0\";
case 1: return \"lvx %0,%y1\";
case 2: return \"vor %0,%1,%1\";
- case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
- case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
- case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ case 3: return \"#\";
+ case 4: return \"#\";
+ case 5: return \"#\";
case 6: return output_vec_const_move (operands);
default: abort ();
}
}"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
- (set_attr "length" "*,*,*,16,16,16,*")])
+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+
+(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])"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+"{
+ rs6000_split_altivec_in_gprs (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])"
+ [(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);
+}")
(define_split
[(set (match_operand:V8HI 0 "altivec_register_operand" "")
case 0: return \"stvx %1,%y0\";
case 1: return \"lvx %0,%y1\";
case 2: return \"vor %0,%1,%1\";
- case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
- case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
- case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ case 3: return \"#\";
+ case 4: return \"#\";
+ case 5: return \"#\";
case 6: return output_vec_const_move (operands);
default: abort ();
}
}"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
- (set_attr "length" "*,*,*,16,16,16,*")])
+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+
+(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])"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+"{
+ rs6000_split_altivec_in_gprs (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])"
+ [(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);
+}")
(define_split
[(set (match_operand:V16QI 0 "altivec_register_operand" "")
case 0: return \"stvx %1,%y0\";
case 1: return \"lvx %0,%y1\";
case 2: return \"vor %0,%1,%1\";
- case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
- case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
- case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ case 3: return \"#\";
+ case 4: return \"#\";
+ case 5: return \"#\";
case 6: return output_vec_const_move (operands);
default: abort ();
}
}"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
- (set_attr "length" "*,*,*,16,16,16,*")])
+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+
+(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])"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+"{
+ rs6000_split_altivec_in_gprs (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])"
+ [(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);
+}")
(define_insn "get_vrsave_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
return 0;
#endif
}
+
+/* Return 1 for all valid move insn operand combination involving altivec
+ vectors in gprs. */
+
+int
+altivec_in_gprs_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;
+}
+
\f
/* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address. */
if (target != dest)
emit_move_insn (dest, target);
}
+
+/* Called by altivec splitter.
+ 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
+
+ Splits the move of operands[1] to operands[0].
+ This is done, if GPRs are one of the operands. In this case
+ a sequence of simple move insns has to be issued. The sequence of these
+ move insns has to be done in correct order to avoid early clobber of the
+ base register or destructive overlap of registers.
+*/
+
+void
+rs6000_split_altivec_in_gprs (rtx *operands)
+{
+ int nregs, reg, i, j;
+ enum machine_mode mode;
+
+ /* Calculate number to move (2/4 for 32/64 bit mode). */
+
+ reg = REG_P (operands[0]) ? REGNO (operands[0]) : REGNO (operands[1]);
+ mode = GET_MODE (operands[0]);
+ nregs = HARD_REGNO_NREGS (reg, mode);
+
+ if (REG_P (operands[1])
+ && REG_P (operands[0])
+ && (REGNO (operands[1]) < REGNO (operands[0])))
+ {
+ /* Move register range backwards, if we have destructive overlap. */
+
+ j = nregs;
+ for (i = 0; i < nregs; i++)
+ {
+ j--;
+ operands[i + 2] = operand_subword (operands[0], j, 0, mode);
+ operands[i + 2 + nregs] =
+ operand_subword (operands[1], j, 0, mode);
+ }
+ }
+ else
+ {
+ j = -1;
+
+ 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]);
+ }
+
+ for (i = 0; i < nregs; i++)
+ {
+ /* 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);
+
+ }
+ }
+}
+
\f
/* This page contains routines that are used to determine what the
function prologue and epilogue code will do and write them out. */