OSDN Git Service

* pa.c (pa_adjust_insn_length): dbra and movb insns which have
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Jul 1993 20:22:50 +0000 (20:22 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Jul 1993 20:22:50 +0000 (20:22 +0000)
        their output in a FP register do not need adjustment.
        (output_cbranch, output_bb): Handle conditional jump to the
        following instruction.
        (output_dbra): New function extracted from dbra pattern.
        (output_movb): New function.
        (eq_neq_comparison_operator): New function.
        (movb_comparison_operator): New function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@4888 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/pa/pa.c

index 478ca9e..fc61ca5 100644 (file)
@@ -2543,10 +2543,12 @@ pa_adjust_insn_length (insn, length)
          && ! forward_branch_p (insn))
        return 1;
       /* Adjust dbra insn with short backwards conditional branch with
-        unfilled delay slot -- only for case where counter is in a register. */
+        unfilled delay slot -- only for case where counter is in a 
+        general register register. */
       else if (GET_CODE (pat) == PARALLEL
               && GET_CODE (XVECEXP (pat, 0, 1)) == SET
               && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == REG
+              && ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0)) 
               && length == 1
               && ! forward_branch_p (insn))
        return 1;
@@ -3250,10 +3252,18 @@ output_cbranch (operands, nullify, length, negated, insn)
   rtx *operands;
   int nullify, length, negated;
   rtx insn;
-{ 
+{
   static char buf[100];
   int useskip = 0;
 
+  /* A conditional branch to the following instruction (eg the delay slot) is
+     asking for a disaster.  This can happen when not optimizing.
+
+     In such cases it is safe to emit nothing.  */
+
+  if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
+    return "";
+  
   /* If this is a long branch with its delay slot unfilled, set `nullify'
      as it can nullify the delay slot and save a nop.  */
   if (length == 2 && dbr_sequence_length () == 0)
@@ -3343,10 +3353,18 @@ output_bb (operands, nullify, length, negated, insn, which)
   int nullify, length, negated;
   rtx insn;
   int which;
-{ 
+{
   static char buf[100];
   int useskip = 0;
 
+  /* A conditional branch to the following instruction (eg the delay slot) is
+     asking for a disaster.  I do not think this can happen as this pattern
+     is only used when optimizing; jump optimization should eliminate the 
+     jump.  But be prepared just in case.  */
+     
+  if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
+    return "";
+  
   /* If this is a long branch with its delay slot unfilled, set `nullify'
      as it can nullify the delay slot and save a nop.  */
   if (length == 2 && dbr_sequence_length () == 0)
@@ -3441,6 +3459,197 @@ output_bb (operands, nullify, length, negated, insn, which)
   return buf;
 }
 
+/* Return the output template for emitting a dbra type insn.
+
+   Note it may perform some output operations on its own before
+   returning the final output string.  */
+char *
+output_dbra (operands, insn, which_alternative)
+     rtx *operands;
+     rtx insn;
+     int which_alternative;
+{
+
+  /* A conditional branch to the following instruction (eg the delay slot) is
+     asking for a disaster.  Be prepared!  */
+
+  if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
+    {
+      if (which_alternative == 0)
+       return "ldo %1(%0),%0";
+      else if (which_alternative == 1)
+       {
+         output_asm_insn ("fstws %0,-16(0,%%r30)",operands);
+         output_asm_insn ("ldw -16(0,%%r30),%4",operands);
+         output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands);
+         return "fldws -16(0,%%r30),%0";
+       }
+      else
+       {
+         output_asm_insn ("ldw %0,%4", operands);
+         return "ldo %1(%4),%4\n\tstw %4,%0";
+       }
+    }
+
+  if (which_alternative == 0)
+    {
+      int nullify = INSN_ANNULLED_BRANCH_P (insn);
+      int length = get_attr_length (insn);
+
+      /* If this is a long branch with its delay slot unfilled, set `nullify'
+        as it can nullify the delay slot and save a nop.  */
+      if (length == 2 && dbr_sequence_length () == 0)
+       nullify = 1;
+
+      /* If this is a short forward conditional branch which did not get
+        its delay slot filled, the delay slot can still be nullified.  */
+      if (! nullify && length == 1 && dbr_sequence_length () == 0)
+       nullify = forward_branch_p (insn);
+
+      /* Handle short versions first.  */
+      if (length == 1 && nullify)
+       return "addib,%C2,n %1,%0,%3";
+      else if (length == 1 && ! nullify)
+       return "addib,%C2 %1,%0,%3";
+      else if (length == 2)
+       {
+         /* Handle weird backwards branch with a fulled delay slot 
+            which is nullified.  */
+         if (dbr_sequence_length () != 0
+             && ! forward_branch_p (insn)
+             && nullify)
+           return "addib,%N2,n %1,%0,.+12\n\tbl %3,0";
+         
+         /* Handle normal cases.  */  
+         if (nullify)
+           return "addi,%N2 %1,%0,%0\n\tbl,n %3,0";
+         else
+           return "addi,%N2 %1,%0,%0\n\tbl %3,0";
+       }
+      else
+       abort();
+    }
+  /* Deal with gross reload from FP register case.  */
+  else if (which_alternative == 1)
+    {
+      /* Move loop counter from FP register to MEM then into a GR,
+        increment the GR, store the GR into MEM, and finally reload
+        the FP register from MEM from within the branch's delay slot.  */ 
+      output_asm_insn ("fstws %0,-16(0,%%r30)\n\tldw -16(0,%%r30),%4",operands);
+      output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands);
+      if (get_attr_length (insn) == 6)
+       return "comb,%S2 0,%4,%3\n\tfldws -16(0,%%r30),%0";
+      else
+       return "comclr,%B2 0,%4,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0";
+    }
+  /* Deal with gross reload from memory case.  */
+  else
+    {
+      /* Reload loop counter from memory, the store back to memory
+        happens in the branch's delay slot.   */
+      output_asm_insn ("ldw %0,%4", operands);
+      if (get_attr_length (insn) == 3)
+       return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
+      else
+       return "addi,%N2 %1,%4,%0\n\tbl %3,0\n\tstw %4,%0";
+    }
+}
+
+/* Return the output template for emitting a dbra type insn.
+
+   Note it may perform some output operations on its own before
+   returning the final output string.  */
+char *
+output_movb (operands, insn, which_alternative, reverse_comparison)
+     rtx *operands;
+     rtx insn;
+     int which_alternative;
+     int reverse_comparison;
+{
+
+  /* A conditional branch to the following instruction (eg the delay slot) is
+     asking for a disaster.  Be prepared!  */
+
+  if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
+    {
+      if (which_alternative == 0)
+       return "copy %1,%0";
+      else if (which_alternative == 1)
+       {
+         output_asm_insn ("fstws %1,-16(0,%%r30)",operands);
+         return "fldws -16(0,%%r30),%0";
+       }
+      else
+       return "stw %1,%0";
+    }
+
+  /* Support the second variant.  */
+  if (reverse_comparison)
+    PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
+
+  if (which_alternative == 0)
+    {
+      int nullify = INSN_ANNULLED_BRANCH_P (insn);
+      int length = get_attr_length (insn);
+
+      /* If this is a long branch with its delay slot unfilled, set `nullify'
+        as it can nullify the delay slot and save a nop.  */
+      if (length == 2 && dbr_sequence_length () == 0)
+       nullify = 1;
+
+      /* If this is a short forward conditional branch which did not get
+        its delay slot filled, the delay slot can still be nullified.  */
+      if (! nullify && length == 1 && dbr_sequence_length () == 0)
+       nullify = forward_branch_p (insn);
+
+      /* Handle short versions first.  */
+      if (length == 1 && nullify)
+       return "movb,%C2,n %1,%0,%3";
+      else if (length == 1 && ! nullify)
+       return "movb,%C2 %1,%0,%3";
+      else if (length == 2)
+       {
+         /* Handle weird backwards branch with a fulled delay slot 
+            which is nullified.  */
+         if (dbr_sequence_length () != 0
+             && ! forward_branch_p (insn)
+             && nullify)
+           return "movb,%N2,n %1,%0,.+12\n\ttbl %3,0";
+         
+         /* Handle normal cases.  */  
+         if (nullify)
+           return "or,%N2 %1,%%r0,%0\n\tbl,n %3,0";
+         else
+           return "or,%N2 %1,%%r0,%0\n\tbl %3,0";
+       }
+      else
+       abort();
+    }
+  /* Deal with gross reload from FP register case.  */
+  else if (which_alternative == 1)
+    {
+      /* Move loop counter from FP register to MEM then into a GR,
+        increment the GR, store the GR into MEM, and finally reload
+        the FP register from MEM from within the branch's delay slot.  */ 
+      output_asm_insn ("fstws %1,-16(0,%%r30)",operands);
+      if (get_attr_length (insn) == 3)
+       return "comb,%S2 0,%1,%3\n\tfldws -16(0,%%r30),%0";
+      else
+       return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0";
+    }
+  /* Deal with gross reload from memory case.  */
+  else
+    {
+      /* Reload loop counter from memory, the store back to memory
+        happens in the branch's delay slot.   */
+      if (get_attr_length (insn) == 2)
+       return "comb,%S2 0,%1,%3\n\tstw %1,%0";
+      else
+       return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tstw %1,%0";
+    }
+}
+
+
 extern struct obstack *saveable_obstack;
 
 /* In HPUX 8.0's shared library scheme, special relocations are needed
@@ -3603,3 +3812,22 @@ forward_branch_p (insn)
   return (insn == label);
 }
 
+/* Return 1 if OP is an equality comparison, else return 0.  */
+int
+eq_neq_comparison_operator (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
+}
+
+/* Return 1 if OP is an operator suitable for use in a movb instruction.  */
+int
+movb_comparison_operator (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return (GET_CODE (op) == EQ || GET_CODE (op) == NE
+         || GET_CODE (op) == LT || GET_CODE (op) == GE);
+}
+