aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHerman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>2001-01-22 11:29:14 +0100
committerMichael Hayes <m.hayes@gcc.gnu.org>2001-01-22 10:29:14 +0000
commit5078f5eb76d9796bfb97fff2a269508e71b12ad2 (patch)
tree7a7bfb70cceb48673b66bf32e58f9ae275929e39
parent1a938e38a0860429ac79db5edd5a0df9fb184b82 (diff)
downloadgcc-5078f5eb76d9796bfb97fff2a269508e71b12ad2.zip
gcc-5078f5eb76d9796bfb97fff2a269508e71b12ad2.tar.gz
gcc-5078f5eb76d9796bfb97fff2a269508e71b12ad2.tar.bz2
c4x.c (c4x_check_legit_addr): Only check CONST.
* 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. From-SVN: r39180
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/c4x/c4x-protos.h2
-rw-r--r--gcc/config/c4x/c4x.c102
-rw-r--r--gcc/config/c4x/c4x.md14
4 files changed, 102 insertions, 29 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eda0a28..d68d612 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/c4x/c4x-protos.h b/gcc/config/c4x/c4x-protos.h
index 8c8b770..4814e97 100644
--- a/gcc/config/c4x/c4x-protos.h
+++ b/gcc/config/c4x/c4x-protos.h
@@ -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));
diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c
index 496da47..a23b3c8 100644
--- a/gcc/config/c4x/c4x.c
+++ b/gcc/config/c4x/c4x.c
@@ -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
diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md
index 5d2656c..3a81ef6 100644
--- a/gcc/config/c4x/c4x.md
+++ b/gcc/config/c4x/c4x.md
@@ -377,10 +377,12 @@
(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")))
@@ -5133,7 +5135,8 @@
"! 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")])
@@ -5181,7 +5184,8 @@
"! 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")])