summaryrefslogtreecommitdiff
path: root/gcc/config/visium
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/visium')
-rw-r--r--gcc/config/visium/visium-protos.h3
-rw-r--r--gcc/config/visium/visium.c100
-rw-r--r--gcc/config/visium/visium.md98
3 files changed, 127 insertions, 74 deletions
diff --git a/gcc/config/visium/visium-protos.h b/gcc/config/visium/visium-protos.h
index 484d01e477d..9dcbc67035f 100644
--- a/gcc/config/visium/visium-protos.h
+++ b/gcc/config/visium/visium-protos.h
@@ -49,7 +49,8 @@ extern void visium_split_cbranch (enum rtx_code, rtx, rtx, rtx);
extern const char *output_ubranch (rtx, rtx_insn *);
extern const char *output_cbranch (rtx, enum rtx_code, enum machine_mode, int,
rtx_insn *);
-extern void split_double_move (rtx *, enum machine_mode);
+extern void visium_split_double_move (rtx *, enum machine_mode);
+extern void visium_split_double_add (enum rtx_code, rtx, rtx, rtx);
extern void visium_expand_copysign (rtx *, enum machine_mode);
extern void visium_expand_int_cstore (rtx *, enum machine_mode);
extern void visium_expand_fp_cstore (rtx *, enum machine_mode);
diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c
index cd28f9bf90a..44f471a1a49 100644
--- a/gcc/config/visium/visium.c
+++ b/gcc/config/visium/visium.c
@@ -2026,7 +2026,7 @@ visium_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
/* Split a double move of OPERANDS in MODE. */
void
-split_double_move (rtx *operands, enum machine_mode mode)
+visium_split_double_move (rtx *operands, enum machine_mode mode)
{
bool swap = false;
@@ -2076,14 +2076,74 @@ split_double_move (rtx *operands, enum machine_mode mode)
}
}
+/* Split a double addition or subtraction of operands. */
+
+void
+visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2)
+{
+ rtx op3 = gen_lowpart (SImode, op0);
+ rtx op4 = gen_lowpart (SImode, op1);
+ rtx op5;
+ rtx op6 = gen_highpart (SImode, op0);
+ rtx op7 = (op1 == const0_rtx ? op1 : gen_highpart (SImode, op1));
+ rtx op8;
+
+ /* If operand #2 is a small constant, then its high part is null. */
+ if (CONST_INT_P (op2))
+ {
+ HOST_WIDE_INT val = INTVAL (op2);
+
+ if (val < 0)
+ {
+ code = (code == MINUS ? PLUS : MINUS);
+ val = -val;
+ }
+
+ op5 = gen_int_mode (val, SImode);
+ op8 = const0_rtx;
+ }
+ else
+ {
+ op5 = gen_lowpart (SImode, op2);
+ op8 = gen_highpart (SImode, op2);
+ }
+
+ /* This is the {add,sub,neg}si3_insn_set_flags pattern. */
+ rtx x;
+ if (op4 == const0_rtx)
+ x = gen_rtx_NEG (SImode, op5);
+ else
+ x = gen_rtx_fmt_ee (code, SImode, op4, op5);
+ rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
+ XVECEXP (pat, 0, 0) = gen_rtx_SET (op3, x);
+ rtx flags = gen_rtx_REG (CC_NOOVmode, FLAGS_REGNUM);
+ x = gen_rtx_COMPARE (CC_NOOVmode, shallow_copy_rtx (x), const0_rtx);
+ XVECEXP (pat, 0, 1) = gen_rtx_SET (flags, x);
+ emit_insn (pat);
+
+ /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern. */
+ if (op8 == const0_rtx)
+ x = op7;
+ else
+ x = gen_rtx_fmt_ee (code, SImode, op7, op8);
+ x = gen_rtx_fmt_ee (code, SImode, x, gen_rtx_LTU (SImode, flags, const0_rtx));
+ pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
+ XVECEXP (pat, 0, 0) = gen_rtx_SET (op6, x);
+ flags = gen_rtx_REG (CCmode, FLAGS_REGNUM);
+ XVECEXP (pat, 0, 1) = gen_rtx_CLOBBER (VOIDmode, flags);
+ emit_insn (pat);
+
+ visium_flags_exposed = true;
+}
+
/* Expand a copysign of OPERANDS in MODE. */
void
visium_expand_copysign (rtx *operands, enum machine_mode mode)
{
- rtx dest = operands[0];
- rtx op0 = operands[1];
- rtx op1 = operands[2];
+ rtx op0 = operands[0];
+ rtx op1 = operands[1];
+ rtx op2 = operands[2];
rtx mask = force_reg (SImode, GEN_INT (0x7fffffff));
rtx x;
@@ -2091,37 +2151,37 @@ visium_expand_copysign (rtx *operands, enum machine_mode mode)
the FPU on the MCM have a non-standard behavior wrt NaNs. */
gcc_assert (mode == SFmode);
- /* First get all the non-sign bits of OP0. */
- if (GET_CODE (op0) == CONST_DOUBLE)
+ /* First get all the non-sign bits of op1. */
+ if (GET_CODE (op1) == CONST_DOUBLE)
{
- if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
- op0 = simplify_unary_operation (ABS, mode, op0, mode);
- if (op0 != CONST0_RTX (mode))
+ if (real_isneg (CONST_DOUBLE_REAL_VALUE (op1)))
+ op1 = simplify_unary_operation (ABS, mode, op1, mode);
+ if (op1 != CONST0_RTX (mode))
{
long l;
- REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op0), l);
- op0 = force_reg (SImode, GEN_INT (trunc_int_for_mode (l, SImode)));
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op1), l);
+ op1 = force_reg (SImode, GEN_INT (trunc_int_for_mode (l, SImode)));
}
}
else
{
- op0 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op0));
- op0 = force_reg (SImode, gen_rtx_AND (SImode, op0, mask));
+ op1 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op1));
+ op1 = force_reg (SImode, gen_rtx_AND (SImode, op1, mask));
}
- /* Then get the sign bit of OP1. */
+ /* Then get the sign bit of op2. */
mask = force_reg (SImode, gen_rtx_NOT (SImode, mask));
- op1 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op1));
- op1 = force_reg (SImode, gen_rtx_AND (SImode, op1, mask));
+ op2 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op2));
+ op2 = force_reg (SImode, gen_rtx_AND (SImode, op2, mask));
/* Finally OR the two values. */
- if (op0 == CONST0_RTX (SFmode))
- x = op1;
+ if (op1 == CONST0_RTX (SFmode))
+ x = op2;
else
- x = force_reg (SImode, gen_rtx_IOR (SImode, op0, op1));
+ x = force_reg (SImode, gen_rtx_IOR (SImode, op1, op2));
/* And move the result to the destination. */
- emit_insn (gen_rtx_SET (dest, gen_lowpart (SFmode, x)));
+ emit_insn (gen_rtx_SET (op0, gen_lowpart (SFmode, x)));
}
/* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU. We generate
diff --git a/gcc/config/visium/visium.md b/gcc/config/visium/visium.md
index 09d136f5f0f..41e3e5c5719 100644
--- a/gcc/config/visium/visium.md
+++ b/gcc/config/visium/visium.md
@@ -627,7 +627,7 @@
[(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))]
{
- split_double_move (operands, DImode);
+ visium_split_double_move (operands, DImode);
})
;;
@@ -726,7 +726,7 @@
[(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))]
{
- split_double_move (operands, DFmode);
+ visium_split_double_move (operands, DFmode);
})
;;
@@ -815,31 +815,20 @@
(match_operand:DI 2 "add_operand" "")))]
"")
+; Disfavour the use of add.l because of the early clobber.
+
(define_insn_and_split "*addi3_insn"
[(set (match_operand:DI 0 "register_operand" "=r,r,&r")
(plus:DI (match_operand:DI 1 "register_operand" "%0,0, r")
- (match_operand:DI 2 "add_operand" " J,L, r")))]
+ (match_operand:DI 2 "add_operand" " L,J, r")))]
"ok_for_simple_arith_logic_operands (operands, DImode)"
"#"
"reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:DI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC R_FLAGS))])]
- ""
- [(set_attr "type" "arith2")])
-
-; Disfavour the use of add.l because of the early clobber.
-
-(define_insn "*adddi3_insn_flags"
- [(set (match_operand:DI 0 "register_operand" "=r,r,&r")
- (plus:DI (match_operand:DI 1 "register_operand" "%0,0, r")
- (match_operand:DI 2 "add_operand" " J,L, r")))
- (clobber (reg:CC R_FLAGS))]
- "reload_completed"
- "@
- addi %d0,%2\n\tadc.l %0,%0,r0
- subi %d0,%n2\n\tsubc.l %0,%0,r0
- add.l %d0,%d1,%d2\n\tadc.l %0,%1,%2"
+ [(const_int 0)]
+{
+ visium_split_double_add (PLUS, operands[0], operands[1], operands[2]);
+ DONE;
+}
[(set_attr "type" "arith2")])
;;
@@ -847,7 +836,7 @@
;;
;; Integer Add with Carry
;;
-;; Only SI mode is supported as slt[u] for the sake of cstore.
+;; Only SI mode is supported.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -869,6 +858,16 @@
"adc.l %0,%1,r0"
[(set_attr "type" "arith")])
+(define_insn "*plus_plus_sltu<subst_arith>"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))
+ (ltu:SI (reg R_FLAGS) (const_int 0))))
+ (clobber (reg:CC R_FLAGS))]
+ "reload_completed"
+ "adc.l %0,%1,%2"
+ [(set_attr "type" "arith")])
+
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -955,31 +954,20 @@
(match_operand:DI 2 "add_operand" "")))]
"")
+; Disfavour the use of the sub.l because of the early clobber.
+
(define_insn_and_split "*subdi3_insn"
[(set (match_operand:DI 0 "register_operand" "=r,r,&r")
(minus:DI (match_operand:DI 1 "register_operand" " 0,0, r")
- (match_operand:DI 2 "add_operand" " J,L, r")))]
+ (match_operand:DI 2 "add_operand" " L,J, r")))]
"ok_for_simple_arith_logic_operands (operands, DImode)"
"#"
"reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:DI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC R_FLAGS))])]
- ""
- [(set_attr "type" "arith2")])
-
-; Disfavour the use of the sub.l because of the early clobber.
-
-(define_insn "*subdi3_insn_flags"
- [(set (match_operand:DI 0 "register_operand" "=r,r,&r")
- (minus:DI (match_operand:DI 1 "register_operand" " 0,0, r")
- (match_operand:DI 2 "add_operand" " J,L, r")))
- (clobber (reg:CC R_FLAGS))]
- "reload_completed"
- "@
- subi %d0,%2\n\tsubc.l %0,%0,r0
- addi %d0,%n2\n\tadc.l %0,%0,r0
- sub.l %d0,%d1,%d2\n\tsubc.l %0,%1,%2"
+ [(const_int 0)]
+{
+ visium_split_double_add (MINUS, operands[0], operands[1], operands[2]);
+ DONE;
+}
[(set_attr "type" "arith2")])
;;
@@ -987,7 +975,7 @@
;;
;; Integer Subtract with Carry
;;
-;; Only SI mode is supported as neg<slt[u]> for the sake of cstore.
+;; Only SI mode is supported.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -1009,6 +997,16 @@
"subc.l %0,%1,r0"
[(set_attr "type" "arith")])
+(define_insn "*minus_minus_sltu<subst_arith>"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+ (match_operand:SI 2 "register_operand" "r"))
+ (ltu:SI (reg R_FLAGS) (const_int 0))))
+ (clobber (reg:CC R_FLAGS))]
+ "reload_completed"
+ "subc.l %0,%r1,%2"
+ [(set_attr "type" "arith")])
+
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -1054,17 +1052,11 @@
"ok_for_simple_arith_logic_operands (operands, DImode)"
"#"
"reload_completed"
- [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
- (clobber (reg:CC R_FLAGS))])]
- ""
- [(set_attr "type" "arith2")])
-
-(define_insn "*negdi2_insn_flags"
- [(set (match_operand:DI 0 "register_operand" "=&r")
- (neg:DI (match_operand:DI 1 "register_operand" "r")))
- (clobber (reg:CC R_FLAGS))]
- "reload_completed"
- "sub.l %d0,r0,%d1\n\tsubc.l %0,r0,%1"
+ [(const_int 0)]
+{
+ visium_split_double_add (MINUS, operands[0], const0_rtx, operands[1]);
+ DONE;
+}
[(set_attr "type" "arith2")])
;;