aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2000-11-21 16:59:12 -0800
committerRichard Henderson <rth@gcc.gnu.org>2000-11-21 16:59:12 -0800
commitf940c352debee086372f374dc8cf374b8f485fd7 (patch)
tree6e41af970e3a2919c2aeae37c26a63c0d7900f8e /gcc
parentdfc55970936e74f5305b4170d51f37e33982f901 (diff)
downloadgcc-f940c352debee086372f374dc8cf374b8f485fd7.zip
gcc-f940c352debee086372f374dc8cf374b8f485fd7.tar.gz
gcc-f940c352debee086372f374dc8cf374b8f485fd7.tar.bz2
alpha.c (alpha_split_tfmode_frobsign): New.
* config/alpha/alpha.c (alpha_split_tfmode_frobsign): New. * config/alpha/alpha-protos.h: Declare it. * config/alpha/alpha.md (abstf_internal): Use it. (negtf_internal): Likewise. (andnotdi3): Unstar the name. (movtf_internal): Add o/G alternative. From-SVN: r37634
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/alpha/alpha-protos.h2
-rw-r--r--gcc/config/alpha/alpha.c50
-rw-r--r--gcc/config/alpha/alpha.md55
4 files changed, 67 insertions, 49 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3e7b3d8..f95b9ba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2000-11-21 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_split_tfmode_frobsign): New.
+ * config/alpha/alpha-protos.h: Declare it.
+ * config/alpha/alpha.md (abstf_internal): Use it.
+ (negtf_internal): Likewise.
+ (andnotdi3): Unstar the name.
+ (movtf_internal): Add o/G alternative.
+
2000-11-21 Zack Weinberg <zack@wolery.stanford.edu>
* stringpool.c (stringpool_statistics): Also report number and
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index d70ac7f..c12b92d 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -90,6 +90,8 @@ extern int alpha_split_conditional_move PARAMS ((enum rtx_code, rtx, rtx,
extern void alpha_emit_xfloating_arith PARAMS ((enum rtx_code, rtx[]));
extern void alpha_emit_xfloating_cvt PARAMS ((enum rtx_code, rtx[]));
extern void alpha_split_tfmode_pair PARAMS ((rtx[]));
+extern void alpha_split_tfmode_frobsign PARAMS ((rtx[],
+ rtx (*)(rtx, rtx, rtx)));
extern void alpha_expand_unaligned_load PARAMS ((rtx, rtx, HOST_WIDE_INT,
HOST_WIDE_INT, int));
extern void alpha_expand_unaligned_store PARAMS ((rtx, rtx, HOST_WIDE_INT,
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index b4707f2..d16c58c6 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -2357,6 +2357,10 @@ alpha_emit_xfloating_cvt (code, operands)
operands[1]));
}
+/* Split a TFmode OP[1] into DImode OP[2,3] and likewise for
+ OP[0] into OP[0,1]. Naturally, output operand ordering is
+ little-endian. */
+
void
alpha_split_tfmode_pair (operands)
rtx operands[4];
@@ -2391,6 +2395,52 @@ alpha_split_tfmode_pair (operands)
else
abort ();
}
+
+/* Implement negtf2 or abstf2. Op0 is destination, op1 is source,
+ op2 is a register containing the sign bit, operation is the
+ logical operation to be performed. */
+
+void
+alpha_split_tfmode_frobsign (operands, operation)
+ rtx operands[3];
+ rtx (*operation) PARAMS ((rtx, rtx, rtx));
+{
+ rtx high_bit = operands[2];
+ rtx scratch;
+ int move;
+
+ alpha_split_tfmode_pair (operands);
+
+ /* Detect three flavours of operand overlap. */
+ move = 1;
+ if (rtx_equal_p (operands[0], operands[2]))
+ move = 0;
+ else if (rtx_equal_p (operands[1], operands[2]))
+ {
+ if (rtx_equal_p (operands[0], high_bit))
+ move = 2;
+ else
+ move = -1;
+ }
+
+ if (move < 0)
+ emit_move_insn (operands[0], operands[2]);
+
+ /* ??? If the destination overlaps both source tf and high_bit, then
+ assume source tf is dead in its entirety and use the other half
+ for a scratch register. Otherwise "scratch" is just the proper
+ destination register. */
+ scratch = operands[move < 2 ? 1 : 3];
+
+ emit_insn ((*operation) (scratch, high_bit, operands[3]));
+
+ if (move > 0)
+ {
+ emit_move_insn (operands[0], operands[2]);
+ if (move > 1)
+ emit_move_insn (operands[1], scratch);
+ }
+}
/* Use ext[wlq][lh] as the Architecture Handbook describes for extracting
unaligned data:
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index eb1c2e5..028ce48 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -1187,7 +1187,7 @@
"zapnot %1,15,%0"
[(set_attr "type" "shift")])
-(define_insn "*andnot"
+(define_insn "andnotdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(and:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI"))
(match_operand:DI 2 "reg_or_0_operand" "rJ")))]
@@ -1876,35 +1876,12 @@
(define_insn_and_split "*abstf_internal"
[(set (match_operand:TF 0 "register_operand" "=r")
(abs:TF (match_operand:TF 1 "reg_or_fp0_operand" "rG")))
- (use (match_operand:DI 2 "register_operand" "=r"))]
+ (use (match_operand:DI 2 "register_operand" "r"))]
"TARGET_HAS_XFLOATING_LIBS"
"#"
"&& reload_completed"
[(const_int 0)]
- "
-{
- int move;
- rtx tmp;
-
- alpha_split_tfmode_pair (operands);
-
- move = 1;
- if (rtx_equal_p (operands[0], operands[2]))
- move = 0;
- else if (rtx_equal_p (operands[1], operands[2]))
- move = -1;
-
- if (move < 0)
- emit_move_insn (operands[0], operands[2]);
-
- tmp = gen_rtx_NOT (DImode, operands[4]);
- tmp = gen_rtx_AND (DImode, tmp, operands[3]);
- emit_insn (gen_rtx_SET (VOIDmode, operands[1], tmp));
-
- if (move > 0)
- emit_move_insn (operands[0], operands[2]);
- DONE;
-}")
+ "alpha_split_tfmode_frobsign (operands, gen_andnotdi3); DONE;")
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -1937,32 +1914,12 @@
(define_insn_and_split "*negtf_internal"
[(set (match_operand:TF 0 "register_operand" "=r")
(neg:TF (match_operand:TF 1 "reg_or_fp0_operand" "rG")))
- (use (match_operand:DI 2 "register_operand" "=r"))]
+ (use (match_operand:DI 2 "register_operand" "r"))]
"TARGET_HAS_XFLOATING_LIBS"
"#"
"&& reload_completed"
[(const_int 0)]
- "
-{
- int move;
-
- alpha_split_tfmode_pair (operands);
-
- move = 1;
- if (rtx_equal_p (operands[0], operands[2]))
- move = 0;
- else if (rtx_equal_p (operands[1], operands[2]))
- move = -1;
-
- if (move < 0)
- emit_move_insn (operands[0], operands[2]);
-
- emit_insn (gen_xordi3 (operands[1], operands[3], operands[4]));
-
- if (move > 0)
- emit_move_insn (operands[0], operands[2]);
- DONE;
-}")
+ "alpha_split_tfmode_frobsign (operands, gen_xordi3); DONE;")
(define_insn "*addsf_ieee"
[(set (match_operand:SF 0 "register_operand" "=&f")
@@ -4595,7 +4552,7 @@
(define_insn_and_split "*movtf_internal"
[(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
- (match_operand:TF 1 "input_operand" "roG,r"))]
+ (match_operand:TF 1 "input_operand" "roG,rG"))]
"register_operand (operands[0], TFmode)
|| reg_or_fp0_operand (operands[1], TFmode)"
"#"