/* Generate code from machine description to compute values of attributes.
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This program handles insn attributes and the DEFINE_DELAY and
DEFINE_INSN_RESERVATION definitions.
struct insn_def *next; /* Next insn in chain. */
rtx def; /* The DEFINE_... */
int insn_code; /* Instruction number. */
- int insn_index; /* Expression numer in file, for errors. */
+ int insn_index; /* Expression number in file, for errors. */
int lineno; /* Line number. */
int num_alternatives; /* Number of alternatives. */
int vec_idx; /* Index of attribute vector in `def'. */
int lineno; /* Line number. */
};
+struct attr_value_list
+{
+ struct attr_value *av;
+ struct insn_ent *ie;
+ struct attr_desc *attr;
+ struct attr_value_list *next;
+};
+
/* Listheads of above structures. */
/* This one is indexed by the first character of the attribute name. */
static struct attr_desc *attrs[MAX_ATTRS_INDEX];
static struct insn_def *defs;
static struct delay_desc *delays;
+struct attr_value_list **insn_code_values;
/* Other variables. */
static rtx max_fn (rtx);
static rtx min_fn (rtx);
-#define oballoc(size) obstack_alloc (hash_obstack, size)
+#define oballoc(T) XOBNEW (hash_obstack, T)
+#define oballocvec(T, N) XOBNEWVEC (hash_obstack, T, (N))
/* Hash table for sharing RTL and strings. */
/* Here is how primitive or already-shared RTL's hash
codes are made. */
-#define RTL_HASH(RTL) ((long) (RTL) & 0777777)
+#define RTL_HASH(RTL) ((intptr_t) (RTL) & 0777777)
/* Add an entry to the hash table for RTL with hash code HASHCODE. */
{
struct attr_hash *h;
- h = obstack_alloc (hash_obstack, sizeof (struct attr_hash));
+ h = XOBNEW (hash_obstack, struct attr_hash);
h->hashcode = hashcode;
h->u.rtl = rtl;
h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
{
struct attr_hash *h;
- h = obstack_alloc (hash_obstack, sizeof (struct attr_hash));
+ h = XOBNEW (hash_obstack, struct attr_hash);
h->hashcode = -hashcode;
h->u.str = str;
h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
return h->u.str; /* <-- return if found. */
/* Not found; create a permanent copy and add it to the hash table. */
- new_str = obstack_alloc (hash_obstack, len + 1);
+ new_str = XOBNEWVAR (hash_obstack, char, len + 1);
memcpy (new_str, str, len);
new_str[len] = '\0';
attr_hash_add_string (hashcode, new_str);
case CTZ:
case POPCOUNT:
case PARITY:
+ case BSWAP:
XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
break;
|| insn_alternatives[av->first_insn->def->insn_code]))
return av;
- av = oballoc (sizeof (struct attr_value));
+ av = oballoc (struct attr_value);
av->value = value;
av->next = attr->first_value;
attr->first_value = av;
else
av = get_attr_value (value, attr, id->insn_code);
- ie = oballoc (sizeof (struct insn_ent));
+ ie = oballoc (struct insn_ent);
ie->def = id;
insert_insn_ent (av, ie);
}
no_address_fn[i],
address_fn[i]),
new_attr, ie->def->insn_code);
- new_ie = oballoc (sizeof (struct insn_ent));
+ new_ie = oballoc (struct insn_ent);
new_ie->def = ie->def;
insert_insn_ent (new_av, new_ie);
}
for (length_unit_log = 0; length_or & 1; length_or >>= 1)
length_unit_log++;
}
- printf ("const int length_unit_log = %u;\n", length_unit_log);
+ printf ("EXPORTED_CONST int length_unit_log = %u;\n", length_unit_log);
}
/* Take a COND expression and see if any of the conditions in it can be
rtx defval = XEXP (exp, 1);
rtx new_defval = XEXP (exp, 1);
int len = XVECLEN (exp, 0);
- rtx *tests = xmalloc (len * sizeof (rtx));
+ rtx *tests = XNEWVEC (rtx, len);
int allsame = 1;
rtx ret;
if (GET_CODE (exp) == code)
{
- rtx new = insert_right_side (code, XEXP (exp, 1),
- term, insn_code, insn_index);
- if (new != XEXP (exp, 1))
+ rtx new_rtx = insert_right_side (code, XEXP (exp, 1),
+ term, insn_code, insn_index);
+ if (new_rtx != XEXP (exp, 1))
/* Make a copy of this expression and call recursively. */
- newexp = attr_rtx (code, XEXP (exp, 0), new);
+ newexp = attr_rtx (code, XEXP (exp, 0), new_rtx);
else
newexp = exp;
}
for (i = 0; i < XVECLEN (value, 0); i += 2)
{
- rtx this = simplify_test_exp_in_temp (XVECEXP (value, 0, i),
- insn_code, insn_index);
+ rtx this_cond = simplify_test_exp_in_temp (XVECEXP (value, 0, i),
+ insn_code, insn_index);
- right = insert_right_side (AND, andexp, this,
+ right = insert_right_side (AND, andexp, this_cond,
insn_code, insn_index);
right = insert_right_side (AND, right,
evaluate_eq_attr (exp,
insn_code, insn_index);
/* Add this condition into the AND expression. */
- newexp = attr_rtx (NOT, this);
+ newexp = attr_rtx (NOT, this_cond);
andexp = insert_right_side (AND, andexp, newexp,
insn_code, insn_index);
}
struct attr_desc *attr;
struct attr_value *av;
struct insn_ent *ie;
+ struct attr_value_list *iv;
int i;
rtx newexp = exp;
bool left_alt, right_alt;
would give this insn the values being tested for. */
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)
- if (ie->def->insn_code == insn_code)
- {
- rtx x;
- x = evaluate_eq_attr (exp, av->value, insn_code, insn_index);
- x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
- if (attr_rtx_cost(x) < 20)
- return x;
- }
+ {
+ rtx x;
+
+ av = NULL;
+ if (insn_code_values)
+ {
+ for (iv = insn_code_values[insn_code]; iv; iv = iv->next)
+ if (iv->attr == attr)
+ {
+ av = iv->av;
+ break;
+ }
+ }
+ else
+ {
+ for (av = attr->first_value; av; av = av->next)
+ for (ie = av->first_insn; ie; ie = ie->next)
+ if (ie->def->insn_code == insn_code)
+ goto got_av;
+ }
+
+ if (av)
+ {
+ got_av:
+ x = evaluate_eq_attr (exp, av->value, insn_code, insn_index);
+ x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
+ if (attr_rtx_cost(x) < 20)
+ return x;
+ }
+ }
break;
default:
struct insn_ent *ie;
rtx newexp;
int i;
- struct attr_value_list
- {
- struct attr_value *av;
- struct insn_ent *ie;
- struct attr_desc *attr;
- struct attr_value_list *next;
- };
- struct attr_value_list **insn_code_values;
struct attr_value_list *ivbuf;
struct attr_value_list *iv;
return;
/* Make 2 extra elements, for "code" values -2 and -1. */
- insn_code_values = xcalloc ((insn_code_number + 2),
- sizeof (struct attr_value_list *));
+ insn_code_values = XCNEWVEC (struct attr_value_list *, insn_code_number + 2);
/* Offset the table address so we can index by -2 or -1. */
insn_code_values += 2;
- iv = ivbuf = xmalloc (num_insn_ents * sizeof (struct attr_value_list));
+ iv = ivbuf = XNEWVEC (struct attr_value_list, num_insn_ents);
for (i = 0; i < MAX_ATTRS_INDEX; i++)
for (attr = attrs[i]; attr; attr = attr->next)
free (ivbuf);
free (insn_code_values - 2);
+ insn_code_values = NULL;
}
/* Clear the ATTR_CURR_SIMPLIFIED_P flag in EXP and its subexpressions. */
name_ptr = XSTR (exp, 1);
while ((p = next_comma_elt (&name_ptr)) != NULL)
{
- av = oballoc (sizeof (struct attr_value));
+ av = oballoc (struct attr_value);
av->value = attr_rtx (CONST_STRING, p);
av->next = attr->first_value;
attr->first_value = av;
return 0;
}
-/* Returns nonzero is INNER is contained in EXP. */
-
-static int
-contained_in_p (rtx inner, rtx exp)
-{
- int i, j;
- const char *fmt;
-
- if (rtx_equal_p (inner, exp))
- return 1;
-
- for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
- i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
- switch (*fmt++)
- {
- case 'e':
- case 'u':
- if (contained_in_p (inner, XEXP (exp, i)))
- return 1;
- break;
-
- case 'E':
- for (j = 0; j < XVECLEN (exp, i); j++)
- if (contained_in_p (inner, XVECEXP (exp, i, j)))
- return 1;
- break;
- }
-
- return 0;
-}
-
/* Process DEFINE_PEEPHOLE, DEFINE_INSN, and DEFINE_ASM_ATTRIBUTES. */
static void
{
struct insn_def *id;
- id = oballoc (sizeof (struct insn_def));
+ id = oballoc (struct insn_def);
id->next = defs;
defs = id;
id->def = exp;
have_annul_false = 1;
}
- delay = oballoc (sizeof (struct delay_desc));
+ delay = oballoc (struct delay_desc);
delay->def = def;
delay->num = ++num_delays;
delay->next = delays;
printf ("\n");
}
-/* Search for uses of non-const attributes and write code to cache them. */
-
-static int
-write_expr_attr_cache (rtx p, struct attr_desc *attr)
-{
- const char *fmt;
- int i, ie, j, je;
-
- if (GET_CODE (p) == EQ_ATTR)
- {
- if (XSTR (p, 0) != attr->name)
- return 0;
-
- if (!attr->is_numeric)
- printf (" enum attr_%s ", attr->name);
- else
- printf (" int ");
-
- printf ("attr_%s = get_attr_%s (insn);\n", attr->name, attr->name);
- return 1;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (p));
- ie = GET_RTX_LENGTH (GET_CODE (p));
- for (i = 0; i < ie; i++)
- {
- switch (*fmt++)
- {
- case 'e':
- if (write_expr_attr_cache (XEXP (p, i), attr))
- return 1;
- break;
-
- case 'E':
- je = XVECLEN (p, i);
- for (j = 0; j < je; ++j)
- if (write_expr_attr_cache (XVECEXP (p, i, j), attr))
- return 1;
- break;
- }
- }
-
- return 0;
-}
-
/* Utilities to write in various forms. */
static void
if (! create)
return NULL;
- attr = oballoc (sizeof (struct attr_desc));
+ attr = oballoc (struct attr_desc);
attr->name = DEF_ATTR_STRING (name);
attr->first_value = attr->default_val = NULL;
attr->is_numeric = attr->is_const = attr->is_special = 0;
static void
gen_insn_reserv (rtx def)
{
- struct insn_reserv *decl = oballoc (sizeof (struct insn_reserv));
+ struct insn_reserv *decl = oballoc (struct insn_reserv);
decl->name = DEF_ATTR_STRING (XSTR (def, 0));
decl->default_latency = XINT (def, 1);
if (s == b->insn)
return; /* already got that one */
- b = oballoc (sizeof (struct bypass_list));
+ b = oballoc (struct bypass_list);
b->insn = s;
b->next = all_bypasses;
all_bypasses = b;
if (*p == ',')
{
gen_bypass_1 (base, p - base);
- base = p + 1;
+ do
+ p++;
+ while (ISSPACE (*p));
+ base = p;
}
gen_bypass_1 (base, p - base);
}
printf ("#include \"coretypes.h\"\n");
printf ("#include \"tm.h\"\n");
printf ("#include \"rtl.h\"\n");
+ printf ("#include \"insn-attr.h\"\n");
printf ("#include \"tm_p.h\"\n");
printf ("#include \"insn-config.h\"\n");
printf ("#include \"recog.h\"\n");
printf ("#include \"regs.h\"\n");
printf ("#include \"real.h\"\n");
printf ("#include \"output.h\"\n");
- printf ("#include \"insn-attr.h\"\n");
printf ("#include \"toplev.h\"\n");
printf ("#include \"flags.h\"\n");
printf ("#include \"function.h\"\n");
printf ("#define operands recog_data.operand\n\n");
/* Make `insn_alternatives'. */
- insn_alternatives = oballoc (insn_code_number * sizeof (int));
+ insn_alternatives = oballocvec (int, insn_code_number);
for (id = defs; id; id = id->next)
if (id->insn_code >= 0)
insn_alternatives[id->insn_code] = (1 << id->num_alternatives) - 1;
/* Make `insn_n_alternatives'. */
- insn_n_alternatives = oballoc (insn_code_number * sizeof (int));
+ insn_n_alternatives = oballocvec (int, insn_code_number);
for (id = defs; id; id = id->next)
if (id->insn_code >= 0)
insn_n_alternatives[id->insn_code] = id->num_alternatives;