OSDN Git Service

* c4x.c (c4x_check_legit_addr): Only check CONST. Not if CONST
authorm.hayes <m.hayes@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Jan 2001 10:29:14 +0000 (10:29 +0000)
committerm.hayes <m.hayes@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Jan 2001 10:29:14 +0000 (10:29 +0000)
contains SYMBOL_REF, LABEL_REF and CONST_INT.
(c4x_U_constraint, symbolic_address_operand): Likewise.
(c4x_immed_float_constant): Do not check if CONST_DOUBLE is in
memory.
(c4x_r11_set_p, c4x_check_laj_p): New functions.
* c4x-protos.h (c4x_check_laj_p): Add prototype.
* c4x.md (in_annul_slot_3): Do not allow auto-increment in last
anulling slot because of silicon bug.
(laj, lajv): Call c4x_check_laj_p to check for silicon bug.

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

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

index eda0a28..d68d612 100644 (file)
@@ -1,3 +1,16 @@
+2001-01-22 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+       * c4x.c (c4x_check_legit_addr): Only check CONST.  Not if CONST
+       contains SYMBOL_REF, LABEL_REF and CONST_INT.
+       (c4x_U_constraint, symbolic_address_operand): Likewise.
+       (c4x_immed_float_constant): Do not check if CONST_DOUBLE is in
+       memory.
+       (c4x_r11_set_p, c4x_check_laj_p): New functions.
+       * c4x-protos.h (c4x_check_laj_p): Add prototype.
+       * c4x.md (in_annul_slot_3): Do not allow auto-increment in last 
+       anulling slot because of silicon bug.
+       (laj, lajv): Call c4x_check_laj_p to check for silicon bug.
+
 2001-01-22  Alan Modra <alan@linuxcare.com.au>
 
         * cppexp.c (parse_charconst):  Change `mask' type to agree
index 8c8b770..4814e97 100644 (file)
@@ -121,6 +121,8 @@ extern int c4x_rptb_nop_p PARAMS ((rtx));
 
 extern int c4x_rptb_rpts_p PARAMS ((rtx, rtx));
 
+extern int c4x_check_laj_p PARAMS ((rtx));
+
 extern int c4x_autoinc_operand PARAMS ((rtx, enum machine_mode));
 
 extern int any_operand PARAMS ((rtx, enum machine_mode));
index 496da47..a23b3c8 100644 (file)
@@ -186,6 +186,7 @@ static int c4x_arn_reg_operand PARAMS ((rtx, enum machine_mode, unsigned int));
 static int c4x_arn_mem_operand PARAMS ((rtx, enum machine_mode, unsigned int));
 static void c4x_check_attribute PARAMS ((const char *, tree, tree, tree *));
 static int c4x_parse_pragma PARAMS ((const char *, tree *, tree *));
+static int c4x_r11_set_p PARAMS ((rtx));
 
 /* Called to register all of our global variables with the garbage
    collector.  */
@@ -1558,15 +1559,7 @@ c4x_check_legit_addr (mode, addr, strict)
          return 1;
 
        if (GET_CODE (op1) == CONST)
-         {
-           addr = XEXP (op1, 0);
-           
-           if (GET_CODE (addr) == PLUS
-               && (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
-                   || GET_CODE (XEXP (addr, 0)) == LABEL_REF)
-               && GET_CODE (XEXP (addr, 1)) == CONST_INT)
-             return 1;
-         }
+         return 1;
        return 0;
       }
       break;
@@ -2432,8 +2425,9 @@ c4x_immed_float_constant (op)
   if (GET_CODE (op) != CONST_DOUBLE)
     return 0;
 
-  if (GET_CODE (XEXP (op, 0)) == MEM)
-    return 0;
+  /* Do not check if the CONST_DOUBLE is in memory. If there is a MEM
+     present this only means that a MEM rtx has been generated. It does
+     not mean the rtx is really in memory.  */
 
   return GET_MODE (op) == QFmode || GET_MODE (op) == HFmode;
 }
@@ -2835,14 +2829,9 @@ c4x_U_constraint (op)
      rtx op;
 {
   /* Don't allow direct addressing to an arbitrary constant.  */
-  if (GET_CODE (op) == CONST
-      && GET_CODE (XEXP (op, 0)) == PLUS
-      && (GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
-         || GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF)
-      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
-    return 1;
-
-  return GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF;
+  return GET_CODE (op) == CONST
+        || GET_CODE (op) == SYMBOL_REF
+        || GET_CODE (op) == LABEL_REF;
 }
 
 
@@ -3228,14 +3217,10 @@ symbolic_address_operand (op, mode)
 {
   switch (GET_CODE (op))
     {
+    case CONST:
     case SYMBOL_REF:
     case LABEL_REF:
       return 1;
-    case CONST:
-      op = XEXP (op, 0);
-      return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
-              || GET_CODE (XEXP (op, 0)) == LABEL_REF)
-             && GET_CODE (XEXP (op, 1)) == CONST_INT);
     default:
       return 0;
     }
@@ -4720,6 +4705,75 @@ c4x_rptb_rpts_p (insn, op)
 }
 
 
+/* Check if register r11 is used as the destination of an insn.  */
+
+static int
+c4x_r11_set_p(x)
+    rtx x;
+{
+  RTX_CODE code;
+  rtx set;
+  int i, j;
+  const char *fmt;
+
+  if (x == 0)
+    return 0;
+
+  code = GET_CODE (x);
+  if (code == INSN && GET_CODE (PATTERN (x)) == SEQUENCE)
+    x = XVECEXP (PATTERN (x), 0, XVECLEN (PATTERN (x), 0) - 1);
+
+  if (code == INSN && (set = single_set (x)))
+    return c4x_r11_set_p (SET_DEST (set));
+
+  if (code == REG && REGNO (x) == R11_REGNO)
+    return 1;
+
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+       {
+          if (c4x_r11_set_p (XEXP (x, i)))
+           return 1;
+       }
+      else if (fmt[i] == 'E')
+        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+          if (c4x_r11_set_p (XVECEXP (x, i, j)))
+           return 1;
+    }
+  return 0;
+}
+
+
+/* The c4x sometimes has a problem when the insn before the laj insn
+   sets the r11 register.  Check for this situation.  */
+
+int
+c4x_check_laj_p (insn)
+     rtx insn;
+{
+  insn = prev_nonnote_insn (insn);
+
+  /* If this is the start of the function no nop is needed.  */
+  if (insn == 0)
+    return 0;
+
+  /* If the previous insn is a code label we have to insert a nop. This
+     could be a jump or table jump. We can find the normal jumps by
+     scanning the function but this will not find table jumps.  */
+  if (GET_CODE (insn) == CODE_LABEL)
+    return 1;
+
+  /* If the previous insn sets register r11 we have to insert a nop.  */
+  if (c4x_r11_set_p (insn))
+    return 1;
+
+  /* No nop needed.  */
+  return 0;
+}
+
+
 /* Adjust the cost of a scheduling dependency.  Return the new cost of
    a dependency LINK or INSN on DEP_INSN.  COST is the current cost. 
    A set of an address register followed by a use occurs a 2 cycle
index 5d2656c..3a81ef6 100644 (file)
                (const_string "false")))
 
 /* Disable ldp because the c4x contains a bug. The ldp insn modifies
-   the dp register when the insn is anulled or not.  */
+   the dp register when the insn is anulled or not.
+   Also disable autoincrement insns because of a silicon bug.  */
 (define_attr "in_annul_slot_3" "false,true"
-  (if_then_else (and (eq_attr "cpu" "c4x")
-                    (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,ldp,multi"))
+  (if_then_else (and (and (eq_attr "cpu" "c4x")
+                         (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,ldp,multi"))
+                    (eq_attr "onlyreg_nomod" "true"))
                (const_string "true")
                (const_string "false")))
 
   "! TARGET_C3X"
   "*
    if (final_sequence)
-     return \"laj%U0\\t%C0\";
+     return c4x_check_laj_p (insn)
+        ? \"nop\\n\\tlaj%U0\\t%C0\" : \"laj%U0\\t%C0\";
    else
      return \"call%U0\\t%C0\";"
   [(set_attr "type" "laj")])
   "! TARGET_C3X"
   "*
    if (final_sequence)
-     return \"laj%U1\\t%C1\";
+     return c4x_check_laj_p (insn)
+        ? \"nop\\n\\tlaj%U1\\t%C1\" : \"laj%U1\\t%C1\";
    else
      return \"call%U1\\t%C1\";"
   [(set_attr "type" "laj")])