Commit 3a1f863f by David Edelsohn Committed by David Edelsohn

rs6000.c (altivec_in_gprs_p): Rename to ...

        * 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
parent 2f2846ab
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> 2003-09-22 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa-protos.h: Convert to ISO C90. * config/xtensa/xtensa-protos.h: Convert to ISO C90.
......
...@@ -114,24 +114,24 @@ ...@@ -114,24 +114,24 @@
[(set (match_operand:V4SI 0 "nonimmediate_operand" "") [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
(match_operand:V4SI 1 "input_operand" ""))] (match_operand:V4SI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 "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 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))] (set (match_dup 3) (match_dup 5))]
"{ "{
rs6000_split_altivec_in_gprs (operands); rs6000_split_multireg_move (operands);
}") }")
(define_split (define_split
[(set (match_operand:V4SI 0 "nonimmediate_operand" "") [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
(match_operand:V4SI 1 "input_operand" ""))] (match_operand:V4SI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 "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 2) (match_dup 6))
(set (match_dup 3) (match_dup 7)) (set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8)) (set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))] (set (match_dup 5) (match_dup 9))]
"{ "{
rs6000_split_altivec_in_gprs (operands); rs6000_split_multireg_move (operands);
}") }")
(define_split (define_split
...@@ -176,24 +176,24 @@ ...@@ -176,24 +176,24 @@
[(set (match_operand:V8HI 0 "nonimmediate_operand" "") [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
(match_operand:V8HI 1 "input_operand" ""))] (match_operand:V8HI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 "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 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))] (set (match_dup 3) (match_dup 5))]
"{ "{
rs6000_split_altivec_in_gprs (operands); rs6000_split_multireg_move (operands);
}") }")
(define_split (define_split
[(set (match_operand:V8HI 0 "nonimmediate_operand" "") [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
(match_operand:V8HI 1 "input_operand" ""))] (match_operand:V8HI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 "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 2) (match_dup 6))
(set (match_dup 3) (match_dup 7)) (set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8)) (set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))] (set (match_dup 5) (match_dup 9))]
"{ "{
rs6000_split_altivec_in_gprs (operands); rs6000_split_multireg_move (operands);
}") }")
(define_split (define_split
...@@ -238,24 +238,24 @@ ...@@ -238,24 +238,24 @@
[(set (match_operand:V16QI 0 "nonimmediate_operand" "") [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
(match_operand:V16QI 1 "input_operand" ""))] (match_operand:V16QI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 "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 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))] (set (match_dup 3) (match_dup 5))]
"{ "{
rs6000_split_altivec_in_gprs (operands); rs6000_split_multireg_move (operands);
}") }")
(define_split (define_split
[(set (match_operand:V16QI 0 "nonimmediate_operand" "") [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
(match_operand:V16QI 1 "input_operand" ""))] (match_operand:V16QI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 "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 2) (match_dup 6))
(set (match_dup 3) (match_dup 7)) (set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8)) (set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))] (set (match_dup 5) (match_dup 9))]
"{ "{
rs6000_split_altivec_in_gprs (operands); rs6000_split_multireg_move (operands);
}") }")
(define_split (define_split
...@@ -300,24 +300,24 @@ ...@@ -300,24 +300,24 @@
[(set (match_operand:V4SF 0 "nonimmediate_operand" "") [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
(match_operand:V4SF 1 "input_operand" ""))] (match_operand:V4SF 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 "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 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))] (set (match_dup 3) (match_dup 5))]
"{ "{
rs6000_split_altivec_in_gprs (operands); rs6000_split_multireg_move (operands);
}") }")
(define_split (define_split
[(set (match_operand:V4SF 0 "nonimmediate_operand" "") [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
(match_operand:V4SF 1 "input_operand" ""))] (match_operand:V4SF 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 "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 2) (match_dup 6))
(set (match_dup 3) (match_dup 7)) (set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8)) (set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))] (set (match_dup 5) (match_dup 9))]
"{ "{
rs6000_split_altivec_in_gprs (operands); rs6000_split_multireg_move (operands);
}") }")
(define_insn "get_vrsave_internal" (define_insn "get_vrsave_internal"
......
...@@ -100,7 +100,7 @@ extern int includes_rldic_lshift_p (rtx, rtx); ...@@ -100,7 +100,7 @@ extern int includes_rldic_lshift_p (rtx, rtx);
extern int includes_rldicr_lshift_p (rtx, rtx); extern int includes_rldicr_lshift_p (rtx, rtx);
extern int registers_ok_for_quad_peep (rtx, rtx); extern int registers_ok_for_quad_peep (rtx, rtx);
extern int addrs_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, 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 ccr_bit (rtx, int);
...@@ -125,7 +125,7 @@ extern int mfcr_operation (rtx, enum machine_mode); ...@@ -125,7 +125,7 @@ extern int mfcr_operation (rtx, enum machine_mode);
extern int mtcrf_operation (rtx, enum machine_mode); extern int mtcrf_operation (rtx, enum machine_mode);
extern int lmw_operation (rtx, enum machine_mode); extern int lmw_operation (rtx, enum machine_mode);
extern struct rtx_def *create_TOC_reference (rtx); 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 void rs6000_emit_move (rtx, rtx, enum machine_mode);
extern rtx rs6000_legitimize_address (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, extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
......
...@@ -2200,18 +2200,13 @@ small_data_operand (rtx op ATTRIBUTE_UNUSED, ...@@ -2200,18 +2200,13 @@ small_data_operand (rtx op ATTRIBUTE_UNUSED,
#endif #endif
} }
/* Return 1 for all valid move insn operand combination involving altivec /* Return true if either operand is a general purpose register. */
vectors in gprs. */
int bool
altivec_in_gprs_p (rtx op0, rtx op1) gpr_or_gpr_p (rtx op0, rtx op1)
{ {
if (REG_P (op0) && REGNO_REG_CLASS (REGNO (op0)) == GENERAL_REGS) return ((REG_P (op0) && INT_REGNO_P (REGNO (op0)))
return 1; || (REG_P (op1) && INT_REGNO_P (REGNO (op1))));
if (REG_P (op1) && REGNO_REG_CLASS (REGNO (op1)) == GENERAL_REGS)
return 1;
return 0;
} }
...@@ -9462,14 +9457,16 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1) ...@@ -9462,14 +9457,16 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
emit_move_insn (dest, target); emit_move_insn (dest, target);
} }
/* Called by altivec splitter. /* Called by splitter for multireg moves.
Input: Input:
operands[0] : Destination of move operands[0] : Destination of move
operands[1] : Source of move operands[1] : Source of move
noperands : Size of operands vector
Output: Output:
operands[2-5] ([2-3] in 64 bit) : Destination slots operands[2-n] : Destination slots
operands[6-9] ([4-5] in 64 bit) : Source 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]. Splits the move of operands[1] to operands[0].
This is done, if GPRs are one of the operands. In this case This is done, if GPRs are one of the operands. In this case
...@@ -9479,10 +9476,13 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1) ...@@ -9479,10 +9476,13 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
*/ */
void 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; 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). */ /* Calculate number to move (2/4 for 32/64 bit mode). */
...@@ -9500,8 +9500,8 @@ rs6000_split_altivec_in_gprs (rtx *operands) ...@@ -9500,8 +9500,8 @@ rs6000_split_altivec_in_gprs (rtx *operands)
for (i = 0; i < nregs; i++) for (i = 0; i < nregs; i++)
{ {
j--; j--;
operands[i + 2] = operand_subword (operands[0], j, 0, mode); operands[i+2] = operand_subword (operands[0], j, 0, mode);
operands[i + 2 + nregs] = operands[i+2+nregs] =
operand_subword (operands[1], j, 0, mode); operand_subword (operands[1], j, 0, mode);
} }
} }
...@@ -9512,28 +9512,86 @@ rs6000_split_altivec_in_gprs (rtx *operands) ...@@ -9512,28 +9512,86 @@ rs6000_split_altivec_in_gprs (rtx *operands)
if (GET_CODE (operands[1]) == MEM) if (GET_CODE (operands[1]) == MEM)
{ {
rtx breg; 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]) if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
&& REGNO (breg) < REGNO (operands[0]) + nregs) || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
j = REGNO (breg) - REGNO (operands[0]); {
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++) for (i = 0; i < nregs; i++)
{ {
/* Calculate index to next subword. */ /* Calculate index to next subword. */
j++; ++j;
if (j == nregs) if (j == nregs)
j = 0; j = 0;
operands[i + 2] = operand_subword (operands[0], j, 0, mode); operands[i+2] = operand_subword (dst, j, 0, mode);
operands[i + 2 + nregs] = operands[i+2+nregs] = operand_subword (src, j, 0, mode);
operand_subword (operands[1], 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];
}
} }
} }
} }
......
...@@ -8462,25 +8462,9 @@ ...@@ -8462,25 +8462,9 @@
default: default:
abort (); abort ();
case 0: 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: 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: case 2:
return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\"; return \"#\";
case 3: case 3:
return \"fmr %0,%1\"; return \"fmr %0,%1\";
case 4: case 4:
...@@ -8495,8 +8479,7 @@ ...@@ -8495,8 +8479,7 @@
return \"#\"; return \"#\";
} }
}" }"
[(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*") [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")])
(set_attr "length" "8,8,8,4,4,4,8,12,8,12,16")])
(define_split (define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "") [(set (match_operand:DI 0 "gpc_reg_operand" "")
...@@ -8536,6 +8519,17 @@ ...@@ -8536,6 +8519,17 @@
}") }")
(define_split (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" "") [(set (match_operand:TI 0 "gpc_reg_operand" "")
(match_operand:TI 1 "const_double_operand" ""))] (match_operand:TI 1 "const_double_operand" ""))]
"TARGET_POWERPC64" "TARGET_POWERPC64"
...@@ -8677,7 +8671,7 @@ ...@@ -8677,7 +8671,7 @@
[(parallel [(set (match_operand:TI 0 "general_operand" "") [(parallel [(set (match_operand:TI 0 "general_operand" "")
(match_operand:TI 1 "general_operand" "")) (match_operand:TI 1 "general_operand" ""))
(clobber (scratch:SI))])] (clobber (scratch:SI))])]
"TARGET_STRING || TARGET_POWERPC64" ""
"{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }") "{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }")
;; We say that MQ is clobbered in the last alternative because the first ;; We say that MQ is clobbered in the last alternative because the first
...@@ -8685,11 +8679,12 @@ ...@@ -8685,11 +8679,12 @@
;; while the 2nd alternative would not. We put memory cases first so they ;; 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 ;; are preferred. Otherwise, we'd try to reload the output instead of
;; giving the SCRATCH mq. ;; giving the SCRATCH mq.
(define_insn "*movti_power" (define_insn "*movti_power"
[(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r") [(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")) (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
(clobber (match_scratch:SI 2 "=q,q#X,X,X,X"))] (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))" && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
"* "*
{ {
...@@ -8699,18 +8694,12 @@ ...@@ -8699,18 +8694,12 @@
abort (); abort ();
case 0: case 0:
if (TARGET_STRING)
return \"{stsi|stswi} %1,%P0,16\"; return \"{stsi|stswi} %1,%P0,16\";
case 1: case 1:
return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\"; return \"#\";
case 2: case 2:
/* Normally copy registers with lowest numbered register copied first. return \"#\";
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\";
case 3: case 3:
/* If the address is not used in the output, we can use lsi. Otherwise, /* If the address is not used in the output, we can use lsi. Otherwise,
fall through to generating four loads. */ fall through to generating four loads. */
...@@ -8718,29 +8707,15 @@ ...@@ -8718,29 +8707,15 @@
return \"{lsi|lswi} %0,%P1,16\"; return \"{lsi|lswi} %0,%P1,16\";
/* ... fall through ... */ /* ... fall through ... */
case 4: case 4:
/* If the address register is the same as the register for the lowest- return \"#\";
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\";
} }
}" }"
[(set_attr "type" "store,store,*,load,load") [(set_attr "type" "store,store,*,load,load")])
(set_attr "length" "4,16,16,4,16")])
(define_insn "*movti_string" (define_insn "*movti_string"
[(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r") [(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"))] (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))" && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
"* "*
{ {
...@@ -8748,81 +8723,62 @@ ...@@ -8748,81 +8723,62 @@
{ {
default: default:
abort (); abort ();
case 0: case 0:
if (TARGET_STRING)
return \"{stsi|stswi} %1,%P0,16\"; return \"{stsi|stswi} %1,%P0,16\";
case 1: case 1:
return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\"; return \"#\";
case 2: case 2:
/* Normally copy registers with lowest numbered register copied first. return \"#\";
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\";
case 3: case 3:
/* If the address is not used in the output, we can use lsi. Otherwise, /* If the address is not used in the output, we can use lsi. Otherwise,
fall through to generating four loads. */ 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\"; return \"{lsi|lswi} %0,%P1,16\";
/* ... fall through ... */ /* ... fall through ... */
case 4: case 4:
/* If the address register is the same as the register for the lowest- return \"#\";
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\";
} }
}" }"
[(set_attr "type" "store,store,*,load,load") [(set_attr "type" "store,store,*,load,load")])
(set_attr "length" "4,16,16,4,16")])
(define_insn "*movti_ppc64" (define_insn "*movti_ppc64"
[(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m") [(set (match_operand:TI 0 "nonimmediate_operand" "=r,m,r")
(match_operand:TI 1 "input_operand" "r,m,r"))] (match_operand:TI 1 "input_operand" "r,r,o"))]
"TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode) "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
|| gpc_reg_operand (operands[1], TImode))" || gpc_reg_operand (operands[1], TImode))"
"* "@
{ #
switch (which_alternative) #
{ #"
default: [(set_attr "type" "*,load,store")])
abort ();
case 0: (define_split
/* We normally copy the low-numbered register first. However, if [(set (match_operand:TI 0 "nonimmediate_operand" "")
the first register operand 0 is the same as the second register of (match_operand:TI 1 "input_operand" ""))]
operand 1, we must copy in the opposite order. */ "reload_completed && TARGET_POWERPC64
if (REGNO (operands[0]) == REGNO (operands[1]) + 1) && gpr_or_gpr_p (operands[0], operands[1])"
return \"mr %L0,%L1\;mr %0,%1\"; [(set (match_dup 2) (match_dup 4))
else (set (match_dup 3) (match_dup 5))]
return \"mr %0,%1\;mr %L0,%L1\"; "{
case 1: rs6000_split_multireg_move (operands);
/* 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 (define_split
dead. */ [(set (match_operand:TI 0 "nonimmediate_operand" "")
if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, (match_operand:TI 1 "input_operand" ""))]
operands[1], 0)) "reload_completed && !TARGET_POWERPC64
return \"ld %L0,%L1\;ld %0,%1\"; && gpr_or_gpr_p (operands[0], operands[1])"
else [(set (match_dup 2) (match_dup 6))
return \"ld%U1 %0,%1\;ld %L0,%L1\"; (set (match_dup 3) (match_dup 7))
case 2: (set (match_dup 4) (match_dup 8))
return \"std%U0 %1,%0\;std %L1,%L0\"; (set (match_dup 5) (match_dup 9))]
} "{
}" rs6000_split_multireg_move (operands);
[(set_attr "type" "*,load,store") }")
(set_attr "length" "8,8,8")])
(define_expand "load_multiple" (define_expand "load_multiple"
[(match_par_dup 3 [(set (match_operand:SI 0 "" "") [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment