alpha.c (alpha_split_tfmode_frobsign): New.
authorRichard Henderson <rth@redhat.com>
Wed, 22 Nov 2000 00:59:12 +0000 (16:59 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 22 Nov 2000 00:59:12 +0000 (16:59 -0800)
        * 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

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.md

index 3e7b3d8f835fab259d05b39a969cb241ef74d75a..f95b9ba184918fef41c9d92849be62acaf3bff55 100644 (file)
@@ -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
index d70ac7fe821a9bdc00e84f14dcdfe6321579f52c..c12b92d9c79f4f635fef9010fb595678d62f6e48 100644 (file)
@@ -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,
index b4707f22925d31b2cd6be52ba42b3132b42bfd7c..d16c58c6042ec273b2ba1c10301f1b372fb8c227 100644 (file)
@@ -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);
+    }
+}
 \f
 /* Use ext[wlq][lh] as the Architecture Handbook describes for extracting
    unaligned data:
index eb1c2e5e1d920a01073674279e98ebbeb1072ec8..028ce48739a2f1faed4889dfc1084a9a4ffe1350 100644 (file)
   "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")))]
 (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")
 (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")
 
 (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)"
   "#"