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>
* configure: Regenerated to track ../common/aclocal.m4 changes.

View file

@ -31,11 +31,11 @@
static insn_uint
sub_val (insn_uint val,
insn_field_entry *field,
int val_last_pos,
int first_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));
}
@ -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 */
static int
@ -139,6 +206,7 @@ insn_word_cmp (insn_word_entry *l, insn_word_entry *r)
}
}
/* same as strcmp */
static int
opcode_bit_cmp (opcode_bits *l,
opcode_bits *r)
@ -172,6 +240,8 @@ opcode_bit_cmp (opcode_bits *l,
return 0;
}
/* same as strcmp */
static int
opcode_bits_cmp (opcode_bits *l,
opcode_bits *r)
@ -189,6 +259,7 @@ opcode_bits_cmp (opcode_bits *l,
}
}
/* same as strcmp */
static opcode_bits *
new_opcode_bits (opcode_bits *old_bits,
int value,
@ -255,27 +326,32 @@ insn_list_insert (insn_list **cur_insn_ptr,
duplicate_insn_actions duplicate_action)
{
/* 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,
(*cur_insn_ptr)->insn->words);
if (word_cmp < 0)
{
/* found insertion point - new_insn < cur_insn->next */
int cmp;
/* key#1 sort according to the constant fields of each instruction */
cmp = insn_word_cmp (insn->words, (*cur_insn_ptr)->insn->words);
if (cmp < 0)
break;
}
else if (word_cmp == 0)
{
/* words same, try for bit fields */
int bit_cmp = opcode_bits_cmp (expanded_bits,
(*cur_insn_ptr)->expanded_bits);
if (bit_cmp < 0)
{
/* found insertion point - new_insn < cur_insn->next */
else if (cmp > 0)
continue;
/* key#2 sort according to the expanded bits of each instruction */
cmp = opcode_bits_cmp (expanded_bits, (*cur_insn_ptr)->expanded_bits);
if (cmp < 0)
break;
}
else if (bit_cmp == 0)
{
else if (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)
{
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;
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 */
@ -591,22 +664,21 @@ insns_bit_useless (insn_list *insns,
condition != NULL;
condition = condition->next)
{
printf ("useless %s%s\n",
(condition->type == insn_field_cond_eq ? "=" : "!"),
condition->string);
switch (condition->type)
{
case insn_field_cond_value:
switch (condition->test)
{
case insn_field_cond_ne:
if (((condition->value >> shift) & 1) == value)
if (((condition->value >> shift) & 1)
== (unsigned) value)
/* conditional field excludes the
current value */
is_useless = 0;
break;
case insn_field_cond_eq:
if (((condition->value >> shift) & 1) != value)
if (((condition->value >> shift) & 1)
!= (unsigned) value)
/* conditional field requires the
current value */
is_useless = 0;
@ -853,10 +925,6 @@ gen_entry_expand_opcode (gen_entry *table,
}
else
{
if (options.trace.insn_insertion)
{
}
gen_entry_insert_insn (table, instruction,
table->opcode->word_nr,
table->nr_prefetched_words,
@ -879,7 +947,8 @@ gen_entry_expand_opcode (gen_entry *table,
case insn_field_int:
{
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,
last_pos + 1,
((opcode_nr << width) | val),
@ -913,7 +982,7 @@ gen_entry_expand_opcode (gen_entry *table,
{
case insn_field_cond_value:
{
int value = sub_val (condition->value, field,
int value = sub_val (condition->value, field->last,
first_pos, last_pos);
switch (condition->test)
{
@ -931,27 +1000,51 @@ gen_entry_expand_opcode (gen_entry *table,
case insn_field_cond_field:
{
int value;
/* Find a value for the conditional by
looking back through the previously
defined bits for the specified
conditonal field */
opcode_bits *bit = bits;
opcode_bits *bit;
gen_entry *t;
/* Try to find a value for the
conditional by looking back through
the previously defined bits for the
specified conditional field */
for (bit = bits;
bit != NULL;
bit = bit->next)
{
if (bit->field == condition->field
&& (bit->last - bit->first + 1 == condition->field->width))
{
/* the bit field fully specified
the conditional field's value */
value = sub_val (bit->value, bit->last,
first_pos, last_pos);
break;
}
}
/* Try to find a value by looking
through this and previous tables */
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,
"Conditional `%s' of field `%s' isn't expanded",
condition->string, field->val_string);
value = sub_val (bit->value, field,
first_pos, last_pos);
switch (condition->test)
{
case insn_field_cond_ne: