Problems with conditional instruction-table fields (N!M, N=M, ...).

Was restricting `M' to opcode fields in the current word.
This commit is contained in:
Andrew Cagney 1998-07-28 08:08:54 +00:00
parent f36af4ae61
commit 07c2bd1455
2 changed files with 185 additions and 67 deletions

View file

@ -1,3 +1,28 @@
Tue Jul 28 11:19:43 1998 Andrew Cagney <cagney@b1.cygnus.com>
* ld-insn.c (parse_insn_word): For constant conditional strings,
encode their bit value.
* ld-insn.c (parse_insn_word, parse_insn_words): Allow conditional
operands to refer to fields in earlier instruction words.
* gen.c (sub_val): Replace field argument with val_last_pos.
(gen_entry_expand_opcode): Look in previous tables for a value for
a conditional field as well as the bits from the current table.
(insn_list_insert): Add sort key of instructions where
their operand fields have different conditionals.
(insn_field_cmp): New function.
Sun Apr 26 15:31:55 1998 Tom Tromey <tromey@creche>
* configure: Regenerated to track ../common/aclocal.m4 changes.
* config.in: Ditto.
Sun Apr 26 15:20:08 1998 Tom Tromey <tromey@cygnus.com>
* acconfig.h: New file.
* configure.in: Reverted change of Apr 24; use sinclude again.
Fri Apr 24 14:16:40 1998 Tom Tromey <tromey@creche> Fri Apr 24 14:16:40 1998 Tom Tromey <tromey@creche>
* configure: Regenerated to track ../common/aclocal.m4 changes. * configure: Regenerated to track ../common/aclocal.m4 changes.

View file

@ -31,11 +31,11 @@
static insn_uint static insn_uint
sub_val (insn_uint val, sub_val (insn_uint val,
insn_field_entry *field, int val_last_pos,
int first_pos, int first_pos,
int last_pos) int last_pos)
{ {
return ((val >> (field->last - last_pos)) return ((val >> (val_last_pos - last_pos))
& (((insn_uint)1 << (last_pos - first_pos + 1)) - 1)); & (((insn_uint)1 << (last_pos - first_pos + 1)) - 1));
} }
@ -107,6 +107,73 @@ print_gen_entry_insns (gen_entry *table,
} }
} }
/* same as strcmp */
static int
insn_field_cmp (insn_word_entry *l, insn_word_entry *r)
{
while (1)
{
int bit_nr;
if (l == NULL && r == NULL)
return 0; /* all previous fields the same */
if (l == NULL)
return -1; /* left shorter than right */
if (r == NULL)
return +1; /* left longer than right */
for (bit_nr = 0;
bit_nr < options.insn_bit_size;
bit_nr++)
{
if (l->bit[bit_nr]->field->type != insn_field_string)
continue;
if (r->bit[bit_nr]->field->type != insn_field_string)
continue;
if (l->bit[bit_nr]->field->conditions == NULL)
continue;
if (r->bit[bit_nr]->field->conditions == NULL)
continue;
if (0)
printf ("%s%s%s VS %s%s%s\n",
l->bit[bit_nr]->field->val_string,
l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq ? "=" : "!",
l->bit[bit_nr]->field->conditions->string,
r->bit[bit_nr]->field->val_string,
r->bit[bit_nr]->field->conditions->test == insn_field_cond_eq ? "=" : "!",
r->bit[bit_nr]->field->conditions->string);
if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq
&& r->bit[bit_nr]->field->conditions->test == insn_field_cond_eq)
{
if (l->bit[bit_nr]->field->conditions->type == insn_field_cond_field
&& r->bit[bit_nr]->field->conditions->type == insn_field_cond_field)
/* somewhat arbitrary */
{
int cmp = strcmp (l->bit[bit_nr]->field->conditions->string,
r->bit[bit_nr]->field->conditions->string);
if (cmp != 0)
return cmp;
else
continue;
}
if (l->bit[bit_nr]->field->conditions->type == insn_field_cond_field)
return +1;
if (r->bit[bit_nr]->field->conditions->type == insn_field_cond_field)
return -1;
/* The case of both fields having constant values should have
already have been handled because such fields are converted
into normal constant fields. */
continue;
}
if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq)
return +1; /* left = only */
if (r->bit[bit_nr]->field->conditions->test == insn_field_cond_eq)
return -1; /* right = only */
/* FIXME: Need to some what arbitrarily order conditional lists */
continue;
}
l = l->next;
r = r->next;
}
}
/* same as strcmp */ /* same as strcmp */
static int static int
@ -139,6 +206,7 @@ insn_word_cmp (insn_word_entry *l, insn_word_entry *r)
} }
} }
/* same as strcmp */
static int static int
opcode_bit_cmp (opcode_bits *l, opcode_bit_cmp (opcode_bits *l,
opcode_bits *r) opcode_bits *r)
@ -172,6 +240,8 @@ opcode_bit_cmp (opcode_bits *l,
return 0; return 0;
} }
/* same as strcmp */
static int static int
opcode_bits_cmp (opcode_bits *l, opcode_bits_cmp (opcode_bits *l,
opcode_bits *r) opcode_bits *r)
@ -189,6 +259,7 @@ opcode_bits_cmp (opcode_bits *l,
} }
} }
/* same as strcmp */
static opcode_bits * static opcode_bits *
new_opcode_bits (opcode_bits *old_bits, new_opcode_bits (opcode_bits *old_bits,
int value, int value,
@ -255,27 +326,32 @@ insn_list_insert (insn_list **cur_insn_ptr,
duplicate_insn_actions duplicate_action) duplicate_insn_actions duplicate_action)
{ {
/* insert it according to the order of the fields & bits */ /* insert it according to the order of the fields & bits */
while ((*cur_insn_ptr) != NULL) for (; (*cur_insn_ptr) != NULL; cur_insn_ptr = &(*cur_insn_ptr)->next)
{ {
int word_cmp = insn_word_cmp (insn->words, int cmp;
(*cur_insn_ptr)->insn->words);
if (word_cmp < 0) /* key#1 sort according to the constant fields of each instruction */
{ cmp = insn_word_cmp (insn->words, (*cur_insn_ptr)->insn->words);
/* found insertion point - new_insn < cur_insn->next */ if (cmp < 0)
break; break;
} else if (cmp > 0)
else if (word_cmp == 0) continue;
{
/* words same, try for bit fields */ /* key#2 sort according to the expanded bits of each instruction */
int bit_cmp = opcode_bits_cmp (expanded_bits, cmp = opcode_bits_cmp (expanded_bits, (*cur_insn_ptr)->expanded_bits);
(*cur_insn_ptr)->expanded_bits); if (cmp < 0)
if (bit_cmp < 0)
{
/* found insertion point - new_insn < cur_insn->next */
break; break;
} else if (cmp > 0)
else if (bit_cmp == 0) continue;
{
/* key#3 sort according to the non-constant fields of each instruction */
cmp = insn_field_cmp (insn->words, (*cur_insn_ptr)->insn->words);
if (cmp < 0)
break;
else if (cmp > 0)
continue;
/* duplicate keys, report problem */
switch (duplicate_action) switch (duplicate_action)
{ {
case report_duplicate_insns: case report_duplicate_insns:
@ -302,10 +378,7 @@ insn_list_insert (insn_list **cur_insn_ptr,
(*cur_insn_ptr)->nr_prefetched_words = nr_prefetched_words; (*cur_insn_ptr)->nr_prefetched_words = nr_prefetched_words;
return (*cur_insn_ptr); return (*cur_insn_ptr);
} }
}
}
/* keep looking - new_insn > cur_insn->next */
cur_insn_ptr = &(*cur_insn_ptr)->next;
} }
/* create a new list entry and insert it */ /* create a new list entry and insert it */
@ -591,22 +664,21 @@ insns_bit_useless (insn_list *insns,
condition != NULL; condition != NULL;
condition = condition->next) condition = condition->next)
{ {
printf ("useless %s%s\n",
(condition->type == insn_field_cond_eq ? "=" : "!"),
condition->string);
switch (condition->type) switch (condition->type)
{ {
case insn_field_cond_value: case insn_field_cond_value:
switch (condition->test) switch (condition->test)
{ {
case insn_field_cond_ne: case insn_field_cond_ne:
if (((condition->value >> shift) & 1) == value) if (((condition->value >> shift) & 1)
== (unsigned) value)
/* conditional field excludes the /* conditional field excludes the
current value */ current value */
is_useless = 0; is_useless = 0;
break; break;
case insn_field_cond_eq: case insn_field_cond_eq:
if (((condition->value >> shift) & 1) != value) if (((condition->value >> shift) & 1)
!= (unsigned) value)
/* conditional field requires the /* conditional field requires the
current value */ current value */
is_useless = 0; is_useless = 0;
@ -853,10 +925,6 @@ gen_entry_expand_opcode (gen_entry *table,
} }
else else
{ {
if (options.trace.insn_insertion)
{
}
gen_entry_insert_insn (table, instruction, gen_entry_insert_insn (table, instruction,
table->opcode->word_nr, table->opcode->word_nr,
table->nr_prefetched_words, table->nr_prefetched_words,
@ -879,7 +947,8 @@ gen_entry_expand_opcode (gen_entry *table,
case insn_field_int: case insn_field_int:
{ {
int val; int val;
val = sub_val (field->val_int, field, first_pos, last_pos); val = sub_val (field->val_int, field->last,
first_pos, last_pos);
gen_entry_expand_opcode (table, instruction, gen_entry_expand_opcode (table, instruction,
last_pos + 1, last_pos + 1,
((opcode_nr << width) | val), ((opcode_nr << width) | val),
@ -913,7 +982,7 @@ gen_entry_expand_opcode (gen_entry *table,
{ {
case insn_field_cond_value: case insn_field_cond_value:
{ {
int value = sub_val (condition->value, field, int value = sub_val (condition->value, field->last,
first_pos, last_pos); first_pos, last_pos);
switch (condition->test) switch (condition->test)
{ {
@ -931,27 +1000,51 @@ gen_entry_expand_opcode (gen_entry *table,
case insn_field_cond_field: case insn_field_cond_field:
{ {
int value; int value;
/* Find a value for the conditional by opcode_bits *bit;
looking back through the previously gen_entry *t;
defined bits for the specified /* Try to find a value for the
conditonal field */ conditional by looking back through
opcode_bits *bit = bits; the previously defined bits for the
specified conditional field */
for (bit = bits; for (bit = bits;
bit != NULL; bit != NULL;
bit = bit->next) bit = bit->next)
{ {
if (bit->field == condition->field if (bit->field == condition->field
&& (bit->last - bit->first + 1 == condition->field->width)) && (bit->last - bit->first + 1 == condition->field->width))
{
/* the bit field fully specified /* the bit field fully specified
the conditional field's value */ the conditional field's value */
value = sub_val (bit->value, bit->last,
first_pos, last_pos);
break; break;
} }
}
/* Try to find a value by looking
through this and previous tables */
if (bit == NULL) if (bit == NULL)
{
for (t = table;
t->parent != NULL;
t = t->parent)
{
if (t->parent->opcode->word_nr != condition->field->word_nr)
continue;
if (t->parent->opcode->first <= condition->field->first
&& t->parent->opcode->last >= condition->field->last)
{
/* the table entry fully
specified the condition
field's value */
value = sub_val (t->opcode_nr, t->parent->opcode->last,
first_pos, last_pos);
}
}
}
if (bit == NULL && t == NULL)
error (instruction->line, error (instruction->line,
"Conditional `%s' of field `%s' isn't expanded", "Conditional `%s' of field `%s' isn't expanded",
condition->string, field->val_string); condition->string, field->val_string);
value = sub_val (bit->value, field,
first_pos, last_pos);
switch (condition->test) switch (condition->test)
{ {
case insn_field_cond_ne: case insn_field_cond_ne: