Add support for instruction word conditionals of the form `XXX!YYY'

and XXX=YYY'.  See mn10300 for examples.
This commit is contained in:
Andrew Cagney
1998-04-14 00:00:15 +00:00
parent 27aa0c7e55
commit 346a3d6c11
5 changed files with 428 additions and 79 deletions

View File

@ -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,

View File

@ -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)
{ {

View File

@ -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;

View File

@ -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;
}; };

View File

@ -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;