mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-05 23:26:51 +08:00
Add support for instruction word conditionals of the form `XXX!YYY'
and XXX=YYY'. See mn10300 for examples.
This commit is contained in:
@ -1,3 +1,41 @@
|
|||||||
|
Tue Apr 14 08:44:53 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* igen.h (struct igen_trace_options): Add members insn_expansion
|
||||||
|
and insn_insertion.
|
||||||
|
|
||||||
|
* igen.c (main): Add options -Gtrace-insn-expansion,
|
||||||
|
-Gtrace-insn-insertion and -Gtrace-all.
|
||||||
|
|
||||||
|
* gen.c (gen_entry_expand_insns): Trace each instruction as it is
|
||||||
|
selected for expansion.
|
||||||
|
(gen_entry_expand_opcode): Trace each expanded instruction as it
|
||||||
|
is inserted into the table.
|
||||||
|
|
||||||
|
Mon Apr 13 19:21:47 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* ld-insn.c (parse_insn_word): Parse conditional operators.
|
||||||
|
(parse_insn_word): Verify field conditionals.
|
||||||
|
|
||||||
|
* ld-insn.h: Extend syntax to allow macros and field equality.
|
||||||
|
(struct insn_field_cond): Rename insn_field_exclusion, add type.
|
||||||
|
|
||||||
|
* gen.c (gen_entry_expand_opcode): Check type of conditional.
|
||||||
|
(insns_bit_useless): Ditto.
|
||||||
|
|
||||||
|
* ld-insn.c (parse_macro_record): New function.
|
||||||
|
|
||||||
|
Mon Apr 13 22:37:47 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* ld-insn.h (enum insn_field_type): Add insn_field_invalid.
|
||||||
|
|
||||||
|
* ld-insn.c (parse_insn_word): Check instruction field type
|
||||||
|
correctly initialized.
|
||||||
|
(print_insn_words): Ditto.
|
||||||
|
(insn_field_type_to_str): Ditto.
|
||||||
|
(dump_insn_field): Ditto.
|
||||||
|
|
||||||
|
* gen.c (insns_bit_useless): Ditto.
|
||||||
|
|
||||||
Fri Apr 3 18:08:16 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
Fri Apr 3 18:08:16 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
* gen.h, igen.c (print_include_inline, print_includes,
|
* gen.h, igen.c (print_include_inline, print_includes,
|
||||||
|
241
sim/igen/gen.c
241
sim/igen/gen.c
@ -73,8 +73,8 @@ print_gen_entry_path (line_ref *line,
|
|||||||
{
|
{
|
||||||
if (table->parent == NULL)
|
if (table->parent == NULL)
|
||||||
{
|
{
|
||||||
if (table->top->processor != NULL)
|
if (table->top->model != NULL)
|
||||||
print (line, "%s", table->top->processor);
|
print (line, "%s", table->top->model->name);
|
||||||
else
|
else
|
||||||
print (line, "");
|
print (line, "");
|
||||||
}
|
}
|
||||||
@ -282,9 +282,9 @@ insn_list_insert (insn_list **cur_insn_ptr,
|
|||||||
/* two instructions with the same constant field
|
/* two instructions with the same constant field
|
||||||
values across all words and bits */
|
values across all words and bits */
|
||||||
warning (insn->line,
|
warning (insn->line,
|
||||||
"Location of second (duplicated?) instruction");
|
"Two instructions with identical constant fields\n");
|
||||||
error ((*cur_insn_ptr)->insn->line,
|
error ((*cur_insn_ptr)->insn->line,
|
||||||
"Two instructions with identical constant fields\n");
|
"Location of second (duplicated?) instruction\n");
|
||||||
case merge_duplicate_insns:
|
case merge_duplicate_insns:
|
||||||
/* Add the opcode path to the instructions list */
|
/* Add the opcode path to the instructions list */
|
||||||
if (opcodes != NULL)
|
if (opcodes != NULL)
|
||||||
@ -382,19 +382,19 @@ gen_entry_traverse_tree (lf *file,
|
|||||||
static gen_list *
|
static gen_list *
|
||||||
make_table (insn_table *isa,
|
make_table (insn_table *isa,
|
||||||
decode_table *rules,
|
decode_table *rules,
|
||||||
char *processor)
|
model_entry *model)
|
||||||
{
|
{
|
||||||
insn_entry *insn;
|
insn_entry *insn;
|
||||||
gen_list *entry = ZALLOC (gen_list);
|
gen_list *entry = ZALLOC (gen_list);
|
||||||
entry->table = ZALLOC (gen_entry);
|
entry->table = ZALLOC (gen_entry);
|
||||||
entry->table->top = entry;
|
entry->table->top = entry;
|
||||||
entry->processor = processor;
|
entry->model = model;
|
||||||
entry->isa = isa;
|
entry->isa = isa;
|
||||||
for (insn = isa->insns; insn != NULL; insn = insn->next)
|
for (insn = isa->insns; insn != NULL; insn = insn->next)
|
||||||
{
|
{
|
||||||
if (processor == NULL
|
if (model == NULL
|
||||||
|| insn->processors == NULL
|
|| insn->processors == NULL
|
||||||
|| filter_is_member (insn->processors, processor))
|
|| filter_is_member (insn->processors, model->name))
|
||||||
{
|
{
|
||||||
insn_list_insert (&entry->table->insns,
|
insn_list_insert (&entry->table->insns,
|
||||||
&entry->table->nr_insns,
|
&entry->table->nr_insns,
|
||||||
@ -420,18 +420,21 @@ make_gen_tables (insn_table *isa,
|
|||||||
if (options.gen.multi_sim)
|
if (options.gen.multi_sim)
|
||||||
{
|
{
|
||||||
gen_list **last = &gen->tables;
|
gen_list **last = &gen->tables;
|
||||||
char *processor;
|
model_entry *model;
|
||||||
filter *processors;
|
filter *processors;
|
||||||
if (options.model_filter != NULL)
|
if (options.model_filter != NULL)
|
||||||
processors = options.model_filter;
|
processors = options.model_filter;
|
||||||
else
|
else
|
||||||
processors = isa->model->processors;
|
processors = isa->model->processors;
|
||||||
for (processor = filter_next (processors, "");
|
for (model = isa->model->models;
|
||||||
processor != NULL;
|
model != NULL;
|
||||||
processor = filter_next (processors, processor))
|
model = model->next)
|
||||||
{
|
{
|
||||||
*last = make_table (isa, rules, processor);
|
if (filter_is_member (processors, model->name))
|
||||||
last = &(*last)->next;
|
{
|
||||||
|
*last = make_table (isa, rules, model);
|
||||||
|
last = &(*last)->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -495,12 +498,18 @@ insns_bit_useless (insn_list *insns,
|
|||||||
insn_list *entry;
|
insn_list *entry;
|
||||||
int value = -1;
|
int value = -1;
|
||||||
int is_useless = 1; /* cleared if something actually found */
|
int is_useless = 1; /* cleared if something actually found */
|
||||||
|
|
||||||
|
/* check the instructions for some constant value in at least one of
|
||||||
|
the bit fields */
|
||||||
for (entry = insns; entry != NULL; entry = entry->next)
|
for (entry = insns; entry != NULL; entry = entry->next)
|
||||||
{
|
{
|
||||||
insn_word_entry *word = entry->insn->word[rule->word_nr];
|
insn_word_entry *word = entry->insn->word[rule->word_nr];
|
||||||
insn_bit_entry *bit = word->bit[bit_nr];
|
insn_bit_entry *bit = word->bit[bit_nr];
|
||||||
switch (bit->field->type)
|
switch (bit->field->type)
|
||||||
{
|
{
|
||||||
|
case insn_field_invalid:
|
||||||
|
ASSERT (0);
|
||||||
|
break;
|
||||||
case insn_field_wild:
|
case insn_field_wild:
|
||||||
case insn_field_reserved:
|
case insn_field_reserved:
|
||||||
/* neither useless or useful - ignore */
|
/* neither useless or useful - ignore */
|
||||||
@ -514,7 +523,9 @@ insns_bit_useless (insn_list *insns,
|
|||||||
case decode_find_constants:
|
case decode_find_constants:
|
||||||
case decode_find_mixed:
|
case decode_find_mixed:
|
||||||
/* an integer is useful if its value isn't the same
|
/* an integer is useful if its value isn't the same
|
||||||
between all instructions? */
|
between all instructions. The first time through the
|
||||||
|
value is saved, the second time through (if the
|
||||||
|
values differ) it is marked as useful. */
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
value = bit->value;
|
value = bit->value;
|
||||||
else if (value != bit->value)
|
else if (value != bit->value)
|
||||||
@ -531,9 +542,9 @@ insns_bit_useless (insn_list *insns,
|
|||||||
break;
|
break;
|
||||||
case decode_find_constants:
|
case decode_find_constants:
|
||||||
case decode_find_mixed:
|
case decode_find_mixed:
|
||||||
/* a string field forced to constant */
|
|
||||||
if (filter_is_member (rule->constant_field_names,
|
if (filter_is_member (rule->constant_field_names,
|
||||||
bit->field->val_string))
|
bit->field->val_string))
|
||||||
|
/* a string field forced to constant? */
|
||||||
is_useless = 0;
|
is_useless = 0;
|
||||||
else if (rule->search == decode_find_constants)
|
else if (rule->search == decode_find_constants)
|
||||||
/* the string field isn't constant */
|
/* the string field isn't constant */
|
||||||
@ -542,6 +553,77 @@ insns_bit_useless (insn_list *insns,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given only one constant value has been found, check through all
|
||||||
|
the instructions to see if at least one conditional makes it
|
||||||
|
usefull */
|
||||||
|
if (value >= 0 && is_useless)
|
||||||
|
{
|
||||||
|
for (entry = insns; entry != NULL; entry = entry->next)
|
||||||
|
{
|
||||||
|
insn_word_entry *word = entry->insn->word[rule->word_nr];
|
||||||
|
insn_bit_entry *bit = word->bit[bit_nr];
|
||||||
|
switch (bit->field->type)
|
||||||
|
{
|
||||||
|
case insn_field_invalid:
|
||||||
|
ASSERT (0);
|
||||||
|
break;
|
||||||
|
case insn_field_wild:
|
||||||
|
case insn_field_reserved:
|
||||||
|
case insn_field_int:
|
||||||
|
/* already processed */
|
||||||
|
break;
|
||||||
|
case insn_field_string:
|
||||||
|
switch (rule->search)
|
||||||
|
{
|
||||||
|
case decode_find_strings:
|
||||||
|
case decode_find_constants:
|
||||||
|
/* already processed */
|
||||||
|
break;
|
||||||
|
case decode_find_mixed:
|
||||||
|
/* string field with conditions. If this condition
|
||||||
|
eliminates the value then the compare is useful */
|
||||||
|
if (bit->field->conditions != NULL)
|
||||||
|
{
|
||||||
|
insn_field_cond *condition;
|
||||||
|
int shift = bit->field->last - bit_nr;
|
||||||
|
for (condition = bit->field->conditions;
|
||||||
|
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)
|
||||||
|
/* conditional field excludes the
|
||||||
|
current value */
|
||||||
|
is_useless = 0;
|
||||||
|
break;
|
||||||
|
case insn_field_cond_eq:
|
||||||
|
if (((condition->value >> shift) & 1) != value)
|
||||||
|
/* conditional field requires the
|
||||||
|
current value */
|
||||||
|
is_useless = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case insn_field_cond_field:
|
||||||
|
/* are these handled separatly? */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return is_useless;
|
return is_useless;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -753,6 +835,15 @@ gen_entry_expand_opcode (gen_entry *table,
|
|||||||
{
|
{
|
||||||
/* Only include the hardwired bit information with an entry IF
|
/* Only include the hardwired bit information with an entry IF
|
||||||
that entry (and hence its functions) are being duplicated. */
|
that entry (and hence its functions) are being duplicated. */
|
||||||
|
if (options.trace.insn_expansion)
|
||||||
|
{
|
||||||
|
print_gen_entry_path (table->opcode_rule->line, table, notify);
|
||||||
|
notify (NULL, ": insert %d - %s.%s%s\n",
|
||||||
|
opcode_nr,
|
||||||
|
instruction->format_name,
|
||||||
|
instruction->name,
|
||||||
|
(table->opcode_rule->with_duplicates ? " (duplicated)" : ""));
|
||||||
|
}
|
||||||
if (table->opcode_rule->with_duplicates)
|
if (table->opcode_rule->with_duplicates)
|
||||||
{
|
{
|
||||||
gen_entry_insert_insn (table, instruction,
|
gen_entry_insert_insn (table, instruction,
|
||||||
@ -762,6 +853,10 @@ 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,
|
||||||
@ -773,9 +868,11 @@ gen_entry_expand_opcode (gen_entry *table,
|
|||||||
insn_word_entry *word = instruction->word[table->opcode->word_nr];
|
insn_word_entry *word = instruction->word[table->opcode->word_nr];
|
||||||
insn_field_entry *field = word->bit[bit_nr]->field;
|
insn_field_entry *field = word->bit[bit_nr]->field;
|
||||||
int last_pos = ((field->last < table->opcode->last)
|
int last_pos = ((field->last < table->opcode->last)
|
||||||
? field->last : table->opcode->last);
|
? field->last
|
||||||
|
: table->opcode->last);
|
||||||
int first_pos = ((field->first > table->opcode->first)
|
int first_pos = ((field->first > table->opcode->first)
|
||||||
? field->first : table->opcode->first);
|
? field->first
|
||||||
|
: table->opcode->first);
|
||||||
int width = last_pos - first_pos + 1;
|
int width = last_pos - first_pos + 1;
|
||||||
switch (field->type)
|
switch (field->type)
|
||||||
{
|
{
|
||||||
@ -800,21 +897,77 @@ gen_entry_expand_opcode (gen_entry *table,
|
|||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
int last_val = (table->opcode->is_boolean
|
int last_val = (table->opcode->is_boolean
|
||||||
? 2 : (1 << width));
|
? 2
|
||||||
|
: (1 << width));
|
||||||
for (val = 0; val < last_val; val++)
|
for (val = 0; val < last_val; val++)
|
||||||
{
|
{
|
||||||
/* check to see if the value has been limited */
|
/* check to see if the value has been precluded
|
||||||
insn_field_exclusion *exclusion;
|
(by a conditional) in some way */
|
||||||
for (exclusion = field->exclusions;
|
int is_precluded;
|
||||||
exclusion != NULL;
|
insn_field_cond *condition;
|
||||||
exclusion = exclusion->next)
|
for (condition = field->conditions, is_precluded = 0;
|
||||||
|
condition != NULL && !is_precluded;
|
||||||
|
condition = condition->next)
|
||||||
{
|
{
|
||||||
int value = sub_val (exclusion->value, field,
|
switch (condition->type)
|
||||||
first_pos, last_pos);
|
{
|
||||||
if (value == val)
|
case insn_field_cond_value:
|
||||||
break;
|
{
|
||||||
|
int value = sub_val (condition->value, field,
|
||||||
|
first_pos, last_pos);
|
||||||
|
switch (condition->test)
|
||||||
|
{
|
||||||
|
case insn_field_cond_ne:
|
||||||
|
if (value == val)
|
||||||
|
is_precluded = 1;
|
||||||
|
break;
|
||||||
|
case insn_field_cond_eq:
|
||||||
|
if (value != val)
|
||||||
|
is_precluded = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
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 */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (bit == 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:
|
||||||
|
if (value == val)
|
||||||
|
is_precluded = 1;
|
||||||
|
break;
|
||||||
|
case insn_field_cond_eq:
|
||||||
|
if (value != val)
|
||||||
|
is_precluded = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (exclusion == NULL)
|
if (!is_precluded)
|
||||||
{
|
{
|
||||||
/* Only add additional hardwired bit
|
/* Only add additional hardwired bit
|
||||||
information if the entry is not going to
|
information if the entry is not going to
|
||||||
@ -985,10 +1138,10 @@ gen_entry_expand_insns (gen_entry *table)
|
|||||||
opcode_rule = opcode_rule->next)
|
opcode_rule = opcode_rule->next)
|
||||||
{
|
{
|
||||||
char *discard_reason;
|
char *discard_reason;
|
||||||
if (table->top->processor != NULL
|
if (table->top->model != NULL
|
||||||
&& opcode_rule->model_names != NULL
|
&& opcode_rule->model_names != NULL
|
||||||
&& !filter_is_member (opcode_rule->model_names,
|
&& !filter_is_member (opcode_rule->model_names,
|
||||||
table->top->processor))
|
table->top->model->name))
|
||||||
{
|
{
|
||||||
/* the rule isn't applicable to this processor */
|
/* the rule isn't applicable to this processor */
|
||||||
discard_reason = "wrong model";
|
discard_reason = "wrong model";
|
||||||
@ -1075,15 +1228,7 @@ gen_entry_expand_insns (gen_entry *table)
|
|||||||
table->opcode->parent = table->parent->opcode;
|
table->opcode->parent = table->parent->opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* expand the raw instructions according to the opcode */
|
/* report the rule being used to expand the instructions */
|
||||||
{
|
|
||||||
insn_list *entry;
|
|
||||||
for (entry = table->insns; entry != NULL; entry = entry->next)
|
|
||||||
{
|
|
||||||
gen_entry_insert_expanding (table, entry->insn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.trace.rule_selection)
|
if (options.trace.rule_selection)
|
||||||
{
|
{
|
||||||
print_gen_entry_path (table->opcode_rule->line, table, notify);
|
print_gen_entry_path (table->opcode_rule->line, table, notify);
|
||||||
@ -1098,6 +1243,22 @@ gen_entry_expand_insns (gen_entry *table)
|
|||||||
table->nr_entries);
|
table->nr_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* expand the raw instructions according to the opcode */
|
||||||
|
{
|
||||||
|
insn_list *entry;
|
||||||
|
for (entry = table->insns; entry != NULL; entry = entry->next)
|
||||||
|
{
|
||||||
|
if (options.trace.insn_expansion)
|
||||||
|
{
|
||||||
|
print_gen_entry_path (table->opcode_rule->line, table, notify);
|
||||||
|
notify (NULL, ": expand - %s.%s\n",
|
||||||
|
entry->insn->format_name,
|
||||||
|
entry->insn->name);
|
||||||
|
}
|
||||||
|
gen_entry_insert_expanding (table, entry->insn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* dump the results */
|
/* dump the results */
|
||||||
if (options.trace.entries)
|
if (options.trace.entries)
|
||||||
{
|
{
|
||||||
|
@ -1101,14 +1101,17 @@ main (int argc,
|
|||||||
printf ("\t trace-entries - report entries after a rules application\n");
|
printf ("\t trace-entries - report entries after a rules application\n");
|
||||||
printf ("\t trace-rule-rejection - report each rule as rejected\n");
|
printf ("\t trace-rule-rejection - report each rule as rejected\n");
|
||||||
printf ("\t trace-rule-selection - report each rule as selected\n");
|
printf ("\t trace-rule-selection - report each rule as selected\n");
|
||||||
|
printf ("\t trace-insn-insertion - report each instruction as it is inserted into a decode table\n");
|
||||||
|
printf ("\t trace-rule-expansion - report each instruction as it is expanded (before insertion into a decode table)\n");
|
||||||
|
printf ("\t trace-all - enable all trace options\n");
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf ("\t field-widths - instruction formats specify widths (depreciated)\n");
|
printf ("\t field-widths - instruction formats specify widths (depreciated)\n");
|
||||||
printf ("\t By default, an instruction format specifies bit\n");
|
printf ("\t By default, an instruction format specifies bit\n");
|
||||||
printf ("\t positions\n");
|
printf ("\t positions\n");
|
||||||
printf ("\t This option can now be set directly in the\n");
|
printf ("\t This option can now be set directly in the\n");
|
||||||
printf ("\t instruction table\n");
|
printf ("\t instruction table\n");
|
||||||
printf ("\t jumps - use jumps instead of function calls\n");
|
printf ("\t jumps - use jumps instead of function calls\n");
|
||||||
printf ("\t omit-line-numbers - do not include line number information in the output\n");
|
printf ("\t omit-line-numbers - do not include line number information in the output\n");
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf ("Input options:\n");
|
printf ("Input options:\n");
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
@ -1426,6 +1429,10 @@ main (int argc,
|
|||||||
{
|
{
|
||||||
options.gen.nia = nia_is_void;
|
options.gen.nia = nia_is_void;
|
||||||
}
|
}
|
||||||
|
else if (strcmp (argp, "trace-all") == 0)
|
||||||
|
{
|
||||||
|
memset (&options.trace, enable_p, sizeof (options.trace));
|
||||||
|
}
|
||||||
else if (strcmp (argp, "trace-combine") == 0)
|
else if (strcmp (argp, "trace-combine") == 0)
|
||||||
{
|
{
|
||||||
options.trace.combine = enable_p;
|
options.trace.combine = enable_p;
|
||||||
@ -1442,6 +1449,14 @@ main (int argc,
|
|||||||
{
|
{
|
||||||
options.trace.rule_selection = enable_p;
|
options.trace.rule_selection = enable_p;
|
||||||
}
|
}
|
||||||
|
else if (strcmp (argp, "trace-insn-insertion") == 0)
|
||||||
|
{
|
||||||
|
options.trace.insn_insertion = enable_p;
|
||||||
|
}
|
||||||
|
else if (strcmp (argp, "trace-insn-expansion") == 0)
|
||||||
|
{
|
||||||
|
options.trace.insn_expansion = enable_p;
|
||||||
|
}
|
||||||
else if (strcmp (argp, "jumps") == 0)
|
else if (strcmp (argp, "jumps") == 0)
|
||||||
{
|
{
|
||||||
options.gen.code = generate_jumps;
|
options.gen.code = generate_jumps;
|
||||||
|
@ -86,6 +86,8 @@ typedef struct _igen_trace_options igen_trace_options;
|
|||||||
struct _igen_trace_options {
|
struct _igen_trace_options {
|
||||||
int rule_selection;
|
int rule_selection;
|
||||||
int rule_rejection;
|
int rule_rejection;
|
||||||
|
int insn_insertion;
|
||||||
|
int insn_expansion;
|
||||||
int entries;
|
int entries;
|
||||||
int combine;
|
int combine;
|
||||||
};
|
};
|
||||||
|
@ -118,36 +118,69 @@ parse_insn_word (line_ref *line,
|
|||||||
if (strlen_val == 0)
|
if (strlen_val == 0)
|
||||||
error (line, "Empty value field\n");
|
error (line, "Empty value field\n");
|
||||||
|
|
||||||
/* break out any conditional fields - { "!" <value> } */
|
/* break out any conditional fields - { [ "!" | "=" [ <value> | <field-name> } */
|
||||||
while (*chp == '!')
|
while (*chp == '!' || *chp == '=')
|
||||||
{
|
{
|
||||||
char *start;
|
char *start;
|
||||||
|
char *end;
|
||||||
int len;
|
int len;
|
||||||
insn_field_exclusion *new_exclusion = ZALLOC (insn_field_exclusion);
|
insn_field_cond *new_cond = ZALLOC (insn_field_cond);
|
||||||
insn_field_exclusion **last;
|
insn_field_cond **last;
|
||||||
|
|
||||||
/* what type of conditional field */
|
/* determine the conditional test */
|
||||||
|
switch (*chp)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
new_cond->test = insn_field_cond_eq;
|
||||||
|
break;
|
||||||
|
case '!':
|
||||||
|
new_cond->test = insn_field_cond_ne;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save the value */
|
||||||
chp++;
|
chp++;
|
||||||
chp = skip_spaces (chp);
|
chp = skip_spaces (chp);
|
||||||
/* the value */
|
|
||||||
start = chp;
|
start = chp;
|
||||||
chp = skip_digits (chp);
|
chp = skip_to_separator (chp, "+,:");
|
||||||
len = chp - start;
|
end = back_spaces (start, chp);
|
||||||
|
len = end - start;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
error (line, "Missing or invalid conditional value\n");
|
error (line, "Missing or invalid conditional value\n");
|
||||||
/* fill in the entry */
|
new_cond->string = NZALLOC (char, len + 1);
|
||||||
new_exclusion->string = NZALLOC (char, len + 1);
|
strncpy (new_cond->string, start, len);
|
||||||
strncpy (new_exclusion->string, start, len);
|
|
||||||
new_exclusion->value = a2i (new_exclusion->string);
|
/* determine the conditional type */
|
||||||
|
if (isdigit (*start))
|
||||||
|
{
|
||||||
|
/* [ "!" | "=" ] <value> */
|
||||||
|
new_cond->type = insn_field_cond_value;
|
||||||
|
new_cond->value = a2i (new_cond->string);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* [ "!" | "=" ] <field> - check field valid */
|
||||||
|
new_cond->type = insn_field_cond_field;
|
||||||
|
/* new_cond->field is determined in later */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only a single `=' is permitted. */
|
||||||
|
if ((new_cond->test == insn_field_cond_eq
|
||||||
|
&& new_field->conditions != NULL)
|
||||||
|
|| (new_field->conditions != NULL
|
||||||
|
&& new_field->conditions->test == insn_field_cond_eq))
|
||||||
|
error (line, "Only single conditional when `=' allowed\n");
|
||||||
|
|
||||||
/* insert it */
|
/* insert it */
|
||||||
last = &new_field->exclusions;
|
last = &new_field->conditions;
|
||||||
while (*last != NULL)
|
while (*last != NULL)
|
||||||
last = &(*last)->next;
|
last = &(*last)->next;
|
||||||
*last = new_exclusion;
|
*last = new_cond;
|
||||||
chp = skip_spaces (chp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOW verify that the field ws finished */
|
/* NOW verify that the field was finished */
|
||||||
if (*chp == ',')
|
if (*chp == ',')
|
||||||
{
|
{
|
||||||
chp = skip_spaces (chp + 1);
|
chp = skip_spaces (chp + 1);
|
||||||
@ -156,7 +189,7 @@ parse_insn_word (line_ref *line,
|
|||||||
}
|
}
|
||||||
else if (*chp != '\0')
|
else if (*chp != '\0')
|
||||||
{
|
{
|
||||||
error (line, "Missing field separator");
|
error (line, "Missing field separator\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the value */
|
/* copy the value */
|
||||||
@ -203,8 +236,8 @@ parse_insn_word (line_ref *line,
|
|||||||
filter_parse (&word->field_names, new_field->val_string);
|
filter_parse (&word->field_names, new_field->val_string);
|
||||||
}
|
}
|
||||||
if (new_field->type != insn_field_string
|
if (new_field->type != insn_field_string
|
||||||
&& new_field->exclusions != NULL)
|
&& new_field->conditions != NULL)
|
||||||
error (line, "Exclusions only apply to name fields\n");
|
error (line, "Conditionals can only be applied to named fields\n");
|
||||||
|
|
||||||
/* the copy the position */
|
/* the copy the position */
|
||||||
new_field->pos_string = NZALLOC (char, strlen_pos + 1);
|
new_field->pos_string = NZALLOC (char, strlen_pos + 1);
|
||||||
@ -281,6 +314,9 @@ parse_insn_word (line_ref *line,
|
|||||||
word->bit[i]->field = field;
|
word->bit[i]->field = field;
|
||||||
switch (field->type)
|
switch (field->type)
|
||||||
{
|
{
|
||||||
|
case insn_field_invalid:
|
||||||
|
ASSERT (0);
|
||||||
|
break;
|
||||||
case insn_field_int:
|
case insn_field_int:
|
||||||
word->bit[i]->mask = 1;
|
word->bit[i]->mask = 1;
|
||||||
word->bit[i]->value = ((field->val_int
|
word->bit[i]->value = ((field->val_int
|
||||||
@ -295,6 +331,51 @@ parse_insn_word (line_ref *line,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* go over all fields that have conditionals refering to other
|
||||||
|
fields. Link the fields up. Verify that the two fields have the
|
||||||
|
same size. Verify that the two fields are different */
|
||||||
|
{
|
||||||
|
insn_field_entry *f;
|
||||||
|
for (f = word->first;
|
||||||
|
f->last < options.insn_bit_size;
|
||||||
|
f = f->next)
|
||||||
|
{
|
||||||
|
insn_field_cond *cond;
|
||||||
|
for (cond = f->conditions;
|
||||||
|
cond != NULL;
|
||||||
|
cond = cond->next)
|
||||||
|
{
|
||||||
|
if (cond->type == insn_field_cond_field)
|
||||||
|
{
|
||||||
|
insn_field_entry *field;
|
||||||
|
if (strcmp (cond->string, f->val_string) == 0)
|
||||||
|
error (line, "Conditional of field `%s' refers to its self\n",
|
||||||
|
f->val_string);
|
||||||
|
for (field = word->first;
|
||||||
|
field != NULL;
|
||||||
|
field = field->next)
|
||||||
|
{
|
||||||
|
if (field->type == insn_field_string
|
||||||
|
&& strcmp (field->val_string, cond->string) == 0)
|
||||||
|
{
|
||||||
|
/* found field being refered to by conditonal */
|
||||||
|
cond->field = field;
|
||||||
|
/* check refered to and this field are the
|
||||||
|
same size */
|
||||||
|
if (f->width != field->width)
|
||||||
|
error (line, "Conditional `%s' of field `%s' has different size\n",
|
||||||
|
field->width, f->width);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cond->field == NULL)
|
||||||
|
error (line, "Condition field refers to non-existant field `%s'\n",
|
||||||
|
cond->string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -635,7 +716,8 @@ parse_function_record (table *file,
|
|||||||
table_entry *record,
|
table_entry *record,
|
||||||
function_entry **list,
|
function_entry **list,
|
||||||
function_entry **list_entry,
|
function_entry **list_entry,
|
||||||
int is_internal)
|
int is_internal,
|
||||||
|
model_table *model)
|
||||||
{
|
{
|
||||||
function_entry *new_function;
|
function_entry *new_function;
|
||||||
new_function = ZALLOC (function_entry);
|
new_function = ZALLOC (function_entry);
|
||||||
@ -669,8 +751,12 @@ parse_function_record (table *file,
|
|||||||
while (record != NULL
|
while (record != NULL
|
||||||
&& record_prefix_is (record, '*', nr_function_model_fields))
|
&& record_prefix_is (record, '*', nr_function_model_fields))
|
||||||
{
|
{
|
||||||
filter_parse (&new_function->models,
|
char *model_name = record->field[function_model_name_field] + 1; /*skip `*'*/
|
||||||
record->field[function_model_name_field] + 1 /*skip `*'*/);
|
filter_parse (&new_function->models, model_name);
|
||||||
|
if (!filter_is_subset (model->processors, new_function->models))
|
||||||
|
{
|
||||||
|
error (record->line, "machine model `%s' undefined\n", model_name);
|
||||||
|
}
|
||||||
record = table_read (file);
|
record = table_read (file);
|
||||||
}
|
}
|
||||||
/* parse the function body */
|
/* parse the function body */
|
||||||
@ -683,12 +769,15 @@ parse_function_record (table *file,
|
|||||||
if (!filter_is_subset (options.flags_filter, new_function->flags))
|
if (!filter_is_subset (options.flags_filter, new_function->flags))
|
||||||
{
|
{
|
||||||
if (options.warn.discard)
|
if (options.warn.discard)
|
||||||
notify (new_function->line, "Discarding function entry - filter flags\n");
|
notify (new_function->line, "Discarding function %s - filter flags\n",
|
||||||
|
new_function->name);
|
||||||
}
|
}
|
||||||
else if (!filter_is_subset (options.model_filter, new_function->models))
|
else if (new_function->models != NULL
|
||||||
|
&& !filter_is_common (options.model_filter, new_function->models))
|
||||||
{
|
{
|
||||||
if (options.warn.discard)
|
if (options.warn.discard)
|
||||||
notify (new_function->line, "Discarding function entry - filter models\n");
|
notify (new_function->line, "Discarding function %s - filter models\n",
|
||||||
|
new_function->name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -803,6 +892,34 @@ parse_insn_mnemonic_record (table *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static table_entry *
|
||||||
|
parse_macro_record (table *file,
|
||||||
|
table_entry *record)
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
error (record->line, "Macros are not implemented");
|
||||||
|
#else
|
||||||
|
/* parse the define record */
|
||||||
|
if (record->nr_fields < nr_define_fields)
|
||||||
|
error (record->line, "Incorrect nr fields for define record\n");
|
||||||
|
/* process it */
|
||||||
|
if (!is_filtered_out (options.flags_filter,
|
||||||
|
record->field[record_filter_flags_field])
|
||||||
|
&& !is_filtered_out (options.model_filter,
|
||||||
|
record->field[record_filter_models_field]))
|
||||||
|
{
|
||||||
|
table_define (file,
|
||||||
|
record->line,
|
||||||
|
record->field[macro_name_field],
|
||||||
|
record->field[macro_args_field],
|
||||||
|
record->field[macro_expr_field]);
|
||||||
|
}
|
||||||
|
record = table_read (file);
|
||||||
|
#endif
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
insn_table *
|
insn_table *
|
||||||
load_insn_table (char *file_name,
|
load_insn_table (char *file_name,
|
||||||
cache_entry *cache)
|
cache_entry *cache)
|
||||||
@ -842,7 +959,8 @@ load_insn_table (char *file_name,
|
|||||||
record = parse_function_record (file, record,
|
record = parse_function_record (file, record,
|
||||||
&isa->functions,
|
&isa->functions,
|
||||||
&function,
|
&function,
|
||||||
0/*is-internal*/);
|
0/*is-internal*/,
|
||||||
|
model);
|
||||||
/* convert a string function record into an internal function */
|
/* convert a string function record into an internal function */
|
||||||
if (function != NULL)
|
if (function != NULL)
|
||||||
{
|
{
|
||||||
@ -863,7 +981,8 @@ load_insn_table (char *file_name,
|
|||||||
record = parse_function_record (file, record,
|
record = parse_function_record (file, record,
|
||||||
&isa->functions,
|
&isa->functions,
|
||||||
NULL,
|
NULL,
|
||||||
0/*is-internal*/);
|
0/*is-internal*/,
|
||||||
|
model);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -874,7 +993,8 @@ load_insn_table (char *file_name,
|
|||||||
record = parse_function_record (file, record,
|
record = parse_function_record (file, record,
|
||||||
&isa->functions,
|
&isa->functions,
|
||||||
&function,
|
&function,
|
||||||
1/*is-internal*/);
|
1/*is-internal*/,
|
||||||
|
model);
|
||||||
/* check what was inserted to see if a pseudo-instruction
|
/* check what was inserted to see if a pseudo-instruction
|
||||||
entry also needs to be created */
|
entry also needs to be created */
|
||||||
if (function != NULL)
|
if (function != NULL)
|
||||||
@ -1015,21 +1135,24 @@ load_insn_table (char *file_name,
|
|||||||
record = parse_function_record (file, record,
|
record = parse_function_record (file, record,
|
||||||
&model->statics,
|
&model->statics,
|
||||||
NULL,
|
NULL,
|
||||||
0/*is internal*/);
|
0/*is internal*/,
|
||||||
|
model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case model_internal_record:
|
case model_internal_record:
|
||||||
record = parse_function_record (file, record,
|
record = parse_function_record (file, record,
|
||||||
&model->internals,
|
&model->internals,
|
||||||
NULL,
|
NULL,
|
||||||
1/*is internal*/);
|
1/*is internal*/,
|
||||||
|
model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case model_function_record:
|
case model_function_record:
|
||||||
record = parse_function_record (file, record,
|
record = parse_function_record (file, record,
|
||||||
&model->functions,
|
&model->functions,
|
||||||
NULL,
|
NULL,
|
||||||
0/*is internal*/);
|
0/*is internal*/,
|
||||||
|
model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case insn_record: /* instruction records */
|
case insn_record: /* instruction records */
|
||||||
@ -1118,8 +1241,11 @@ load_insn_table (char *file_name,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case unknown_record:
|
|
||||||
case define_record:
|
case define_record:
|
||||||
|
record = parse_macro_record (file, record);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case unknown_record:
|
||||||
case code_record:
|
case code_record:
|
||||||
error (record->line, "Unknown or unexpected entry\n");
|
error (record->line, "Unknown or unexpected entry\n");
|
||||||
|
|
||||||
@ -1148,6 +1274,9 @@ print_insn_words (lf *file,
|
|||||||
lf_printf (file, "%d.", i2target (options.hi_bit_nr, field->first));
|
lf_printf (file, "%d.", i2target (options.hi_bit_nr, field->first));
|
||||||
switch (field->type)
|
switch (field->type)
|
||||||
{
|
{
|
||||||
|
case insn_field_invalid:
|
||||||
|
ASSERT (0);
|
||||||
|
break;
|
||||||
case insn_field_int:
|
case insn_field_int:
|
||||||
lf_printf (file, "0x%lx", (long) field->val_int);
|
lf_printf (file, "0x%lx", (long) field->val_int);
|
||||||
break;
|
break;
|
||||||
@ -1397,6 +1526,7 @@ insn_field_type_to_str (insn_field_type type)
|
|||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case insn_field_invalid: ASSERT (0); return "(invalid)";
|
||||||
case insn_field_int: return "int";
|
case insn_field_int: return "int";
|
||||||
case insn_field_reserved: return "reserved";
|
case insn_field_reserved: return "reserved";
|
||||||
case insn_field_wild: return "wild";
|
case insn_field_wild: return "wild";
|
||||||
@ -1423,6 +1553,9 @@ dump_insn_field (lf *file,
|
|||||||
lf_printf (file, "%s(type %s)", sep, insn_field_type_to_str (field->type));
|
lf_printf (file, "%s(type %s)", sep, insn_field_type_to_str (field->type));
|
||||||
switch (field->type)
|
switch (field->type)
|
||||||
{
|
{
|
||||||
|
case insn_field_invalid:
|
||||||
|
ASSERT (0);
|
||||||
|
break;
|
||||||
case insn_field_int:
|
case insn_field_int:
|
||||||
lf_printf (file, "%s(val 0x%lx)", sep, (long) field->val_int);
|
lf_printf (file, "%s(val 0x%lx)", sep, (long) field->val_int);
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user