/* Generate code from machine description to compute values of attributes.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* This program handles insn attributes and the DEFINE_DELAY and
DEFINE_INSN_RESERVATION definitions.
`in_struct' (ATTR_CURR_SIMPLIFIED_P): This rtx is fully simplified
for the insn code currently being processed (see optimize_attrs).
`return_val' (ATTR_PERMANENT_P): This rtx is permanent and unique
- (see attr_rtx).
- `volatil' (ATTR_EQ_ATTR_P): During simplify_by_exploding the value of an
- EQ_ATTR rtx is true if !volatil and false if volatil. */
+ (see attr_rtx). */
#define ATTR_IND_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), unchanging))
#define ATTR_CURR_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), in_struct))
#define ATTR_PERMANENT_P(RTX) (RTX_FLAG((RTX), return_val))
-#define ATTR_EQ_ATTR_P(RTX) (RTX_FLAG((RTX), volatil))
#if 0
#define strcmp_check(S1, S2) ((S1) == (S2) \
struct attr_value *default_val; /* Default value for this attribute. */
int lineno : 24; /* Line number. */
unsigned is_numeric : 1; /* Values of this attribute are numeric. */
- unsigned negative_ok : 1; /* Allow negative numeric values. */
- unsigned unsigned_p : 1; /* Make the output function unsigned int. */
unsigned is_const : 1; /* Attribute value constant for each run. */
unsigned is_special : 1; /* Don't call `write_attr_set'. */
unsigned static_p : 1; /* Make the output function static. */
};
-#define NULL_ATTR (struct attr_desc *) NULL
-
/* Structure for each DEFINE_DELAY. */
struct delay_desc
static int *insn_alternatives;
-/* If nonzero, assume that the `alternative' attr has this value.
- This is the hashed, unique string for the numeral
- whose value is chosen alternative. */
-
-static const char *current_alternative_string;
-
/* Used to simplify expressions. */
static rtx true_rtx, false_rtx;
/* Used to reduce calls to `strcmp' */
-static char *alternative_name;
+static const char *alternative_name;
static const char *length_str;
static const char *delay_type_str;
static const char *delay_1_0_str;
(ATTR_IND_SIMPLIFIED_P (EXP) || ATTR_CURR_SIMPLIFIED_P (EXP) ? (EXP) \
: simplify_test_exp (EXP, INSN_CODE, INSN_INDEX))
-/* Simplify (eq_attr ("alternative") ...)
- when we are working with a particular alternative. */
-#define SIMPLIFY_ALTERNATIVE(EXP) \
- if (current_alternative_string \
- && GET_CODE ((EXP)) == EQ_ATTR \
- && XSTR ((EXP), 0) == alternative_name) \
- (EXP) = (XSTR ((EXP), 1) == current_alternative_string \
- ? true_rtx : false_rtx);
-
#define DEF_ATTR_STRING(S) (attr_string ((S), strlen (S)))
/* These are referenced by rtlanal.c and hence need to be defined somewhere.
static rtx zero_fn (rtx);
static rtx one_fn (rtx);
static rtx max_fn (rtx);
+static rtx min_fn (rtx);
static void write_length_unit_log (void);
static rtx simplify_cond (rtx, int, int);
static void clear_struct_flag (rtx);
static void gen_delay (rtx, int);
static void write_test_expr (rtx, int);
static int max_attr_value (rtx, int*);
+static int min_attr_value (rtx, int*);
static int or_attr_value (rtx, int*);
static void walk_attr_value (rtx);
static void write_attr_get (struct attr_desc *);
static rtx attr_alt_intersection (rtx, rtx);
static rtx attr_alt_union (rtx, rtx);
static rtx attr_alt_complement (rtx);
-static bool attr_alt_bit_p (rtx, int);
static rtx mk_attr_alt (int);
#define oballoc(size) obstack_alloc (hash_obstack, size)
ATTR_IND_SIMPLIFIED_P (copy) = ATTR_IND_SIMPLIFIED_P (orig);
ATTR_CURR_SIMPLIFIED_P (copy) = ATTR_CURR_SIMPLIFIED_P (orig);
ATTR_PERMANENT_P (copy) = ATTR_PERMANENT_P (orig);
- ATTR_EQ_ATTR_P (copy) = ATTR_EQ_ATTR_P (orig);
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
break;
}
- if (INTVAL (exp) < 0 && ! attr->negative_ok)
+ if (INTVAL (exp) < 0)
{
message_with_line (attr->lineno,
"negative numeric value specified for attribute %s",
if (attr == 0 || attr->is_numeric)
{
p = XSTR (exp, 0);
- if (attr && attr->negative_ok && *p == '-')
- p++;
for (; *p; p++)
if (! ISDIGIT (*p))
{
have_error = 1;
}
else if (attr
- && (attr->is_numeric != attr2->is_numeric
- || (! attr->negative_ok && attr2->negative_ok)))
+ && attr->is_numeric != attr2->is_numeric)
{
message_with_line (attr->lineno,
"numeric attribute mismatch calling `%s' from `%s'",
}
/* Given an SET_ATTR_ALTERNATIVE expression, convert to the canonical SET.
- It becomes a COND with each test being (eq_attr "alternative "n") */
+ It becomes a COND with each test being (eq_attr "alternative" "n") */
static rtx
convert_set_attr_alternative (rtx exp, struct insn_def *id)
static const char *new_names[] =
{
"*insn_default_length",
+ "*insn_min_length",
"*insn_variable_length_p",
"*insn_current_length"
};
- static rtx (*const no_address_fn[]) (rtx) = {identity_fn, zero_fn, zero_fn};
- static rtx (*const address_fn[]) (rtx) = {max_fn, one_fn, identity_fn};
+ static rtx (*const no_address_fn[]) (rtx)
+ = {identity_fn,identity_fn, zero_fn, zero_fn};
+ static rtx (*const address_fn[]) (rtx)
+ = {max_fn, min_fn, one_fn, identity_fn};
size_t i;
struct attr_desc *length_attr, *new_attr;
struct attr_value *av, *new_av;
return make_numeric_value (max_attr_value (exp, &unknown));
}
+static rtx
+min_fn (rtx exp)
+{
+ int unknown;
+ return make_numeric_value (min_attr_value (exp, &unknown));
+}
+
static void
write_length_unit_log (void)
{
orexp = false_rtx;
andexp = true_rtx;
- if (current_alternative_string)
- clear_struct_flag (value);
-
for (i = 0; i < XVECLEN (value, 0); i += 2)
{
rtx this = simplify_test_exp_in_temp (XVECEXP (value, 0, i),
insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (this);
-
right = insert_right_side (AND, andexp, this,
insn_code, insn_index);
right = insert_right_side (AND, right,
if (address_used)
{
- /* This had `&& current_alternative_string', which seems to be wrong. */
if (! ATTR_IND_SIMPLIFIED_P (exp))
return copy_rtx_unchanging (exp);
return exp;
return result;
}
-/* Tests whether a bit B belongs to the set represented by S. */
-
-static bool
-attr_alt_bit_p (rtx s, int b)
-{
- return XINT (s, 1) ^ ((XINT (s, 0) >> b) & 1);
-}
-
/* Return EQ_ATTR_ALT expression representing set containing elements set
in E. */
{
case AND:
left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (left);
if (left == false_rtx)
return false_rtx;
right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (right);
- if (left == false_rtx)
+ if (right == false_rtx)
return false_rtx;
if (GET_CODE (left) == EQ_ATTR_ALT
case IOR:
left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (left);
if (left == true_rtx)
return true_rtx;
right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (right);
if (right == true_rtx)
return true_rtx;
{
left = SIMPLIFY_TEST_EXP (XEXP (XEXP (exp, 0), 0),
insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (left);
return left;
}
left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
- SIMPLIFY_ALTERNATIVE (left);
if (GET_CODE (left) == NOT)
return XEXP (left, 0);
break;
case EQ_ATTR_ALT:
- if (current_alternative_string)
- return attr_alt_bit_p (exp, atoi (current_alternative_string)) ? true_rtx : false_rtx;
-
if (!XINT (exp, 0))
return XINT (exp, 1) ? true_rtx : false_rtx;
break;
case EQ_ATTR:
- if (current_alternative_string && XSTR (exp, 0) == alternative_name)
- return (XSTR (exp, 1) == current_alternative_string
- ? true_rtx : false_rtx);
-
if (XSTR (exp, 0) == alternative_name)
{
newexp = mk_attr_alt (1 << atoi (XSTR (exp, 1)));
/* Look at the value for this insn code in the specified attribute.
We normally can replace this comparison with the condition that
would give this insn the values being tested for. */
- if (XSTR (exp, 0) != alternative_name
+ if (insn_code >= 0
&& (attr = find_attr (&XSTR (exp, 0), 0)) != NULL)
for (av = attr->first_value; av; av = av->next)
for (ie = av->first_insn; ie; ie = ie->next)
/* We have already simplified this expression. Simplifying it again
won't buy anything unless we weren't given a valid insn code
to process (i.e., we are canonicalizing something.). */
- if (insn_code != -2 /* Seems wrong: && current_alternative_string. */
+ if (insn_code != -2
&& ! ATTR_IND_SIMPLIFIED_P (newexp))
return copy_rtx_unchanging (newexp);
return current_max;
}
+/* Given an attribute value, return the minimum CONST_STRING argument
+ encountered. Set *UNKNOWNP and return 0 if the value is unknown. */
+
+static int
+min_attr_value (rtx exp, int *unknownp)
+{
+ int current_min;
+ int i, n;
+
+ switch (GET_CODE (exp))
+ {
+ case CONST_STRING:
+ current_min = atoi (XSTR (exp, 0));
+ break;
+
+ case COND:
+ current_min = min_attr_value (XEXP (exp, 1), unknownp);
+ for (i = 0; i < XVECLEN (exp, 0); i += 2)
+ {
+ n = min_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
+ if (n < current_min)
+ current_min = n;
+ }
+ break;
+
+ case IF_THEN_ELSE:
+ current_min = min_attr_value (XEXP (exp, 1), unknownp);
+ n = min_attr_value (XEXP (exp, 2), unknownp);
+ if (n < current_min)
+ current_min = n;
+ break;
+
+ default:
+ *unknownp = 1;
+ current_min = INT_MAX;
+ break;
+ }
+
+ return current_min;
+}
+
/* Given an attribute value, return the result of ORing together all
CONST_STRING arguments encountered. Set *UNKNOWNP and return -1
if the numeric value is not known. */
printf ("static ");
if (!attr->is_numeric)
printf ("enum attr_%s\n", attr->name);
- else if (attr->unsigned_p)
- printf ("unsigned int\n");
else
printf ("int\n");
printf ("{\n");
for (av = attr->first_value; av; av = av->next)
- if (av->num_insns != 0)
+ if (av->num_insns == 1)
write_attr_set (attr, 2, av->value, "return", ";",
true_rtx, av->first_insn->def->insn_code,
av->first_insn->def->insn_index);
+ else if (av->num_insns != 0)
+ write_attr_set (attr, 2, av->value, "return", ";",
+ true_rtx, -2, 0);
printf ("}\n\n");
return;
printf ("extract_insn_cached (insn);\n");
}
- write_attr_set (attr, indent + 2, av->value, prefix, suffix,
- known_true, av->first_insn->def->insn_code,
- av->first_insn->def->insn_index);
+ if (av->num_insns == 1)
+ write_attr_set (attr, indent + 2, av->value, prefix, suffix,
+ known_true, av->first_insn->def->insn_code,
+ av->first_insn->def->insn_index);
+ else
+ write_attr_set (attr, indent + 2, av->value, prefix, suffix,
+ known_true, -2, 0);
if (strncmp (prefix, "return", 6))
{
if (!attr->is_numeric)
printf (" enum attr_%s ", attr->name);
- else if (attr->unsigned_p)
- printf (" unsigned int ");
else
printf (" int ");
attr = oballoc (sizeof (struct attr_desc));
attr->name = DEF_ATTR_STRING (name);
attr->first_value = attr->default_val = NULL;
- attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0;
- attr->unsigned_p = attr->static_p = 0;
+ attr->is_numeric = attr->is_const = attr->is_special = 0;
+ attr->static_p = 0;
attr->next = attrs[index];
attrs[index] = attr;
attr->is_numeric = 1;
attr->is_const = 0;
attr->is_special = (special & ATTR_SPECIAL) != 0;
- attr->negative_ok = (special & ATTR_NEGATIVE_OK) != 0;
- attr->unsigned_p = (special & ATTR_UNSIGNED) != 0;
attr->static_p = (special & ATTR_STATIC) != 0;
attr->default_val = get_attr_value (value, attr, -2);
}