-/* This file is part of the program psim.
+/* The IGEN simulator generator for GDB, the GNU Debugger.
- Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
+ Copyright 2002-2020 Free Software Foundation, Inc.
- This program 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 of the License, or
- (at your option) any later version.
+ Contributed by Andrew Cagney.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- */
+ This file is part of GDB.
+
+ This program 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "misc.h"
#include "gen.h"
static insn_uint
-sub_val (insn_uint val,
- insn_field_entry *field,
- int first_pos,
- int last_pos)
+sub_val (insn_uint val, int val_last_pos, int first_pos, int last_pos)
{
- return ((val >> (field->last - last_pos))
- & (((insn_uint)1 << (last_pos - first_pos + 1)) - 1));
+ return ((val >> (val_last_pos - last_pos))
+ & (((insn_uint) 1 << (last_pos - first_pos + 1)) - 1));
}
static void
-update_depth (lf *file,
- gen_entry *entry,
- int depth,
- void *data)
+update_depth (lf *file, gen_entry *entry, int depth, void *data)
{
- int *max_depth = (int*)data;
+ int *max_depth = (int *) data;
if (*max_depth < depth)
*max_depth = depth;
}
gen_entry_depth (gen_entry *table)
{
int depth = 0;
- gen_entry_traverse_tree (NULL,
- table,
- 1,
- NULL, /*start*/
- update_depth,
- NULL, /*end*/
- &depth); /* data */
+ gen_entry_traverse_tree (NULL, table, 1, NULL, /*start */
+ update_depth, NULL, /*end */
+ &depth); /* data */
return depth;
}
static void
-print_gen_entry_path (line_ref *line,
- gen_entry *table,
- error_func *print)
+print_gen_entry_path (line_ref *line, gen_entry *table, error_func *print)
{
if (table->parent == NULL)
{
- if (table->top->processor != NULL)
- print (line, "%s", table->top->processor);
+ if (table->top->model != NULL)
+ print (line, "%s", table->top->model->name);
else
print (line, "");
}
static void
print_gen_entry_insns (gen_entry *table,
error_func *print,
- char *first_message,
- char *next_message)
+ char *first_message, char *next_message)
{
insn_list *i;
char *message;
{
insn_entry *insn = i->insn;
print_gen_entry_path (insn->line, table, print);
- print (NULL, ": %s.%s %s\n",
- insn->format_name,
- insn->name,
- message);
+ print (NULL, ": %s.%s %s\n", insn->format_name, insn->name, message);
if (next_message != NULL)
message = next_message;
}
}
+/* 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, but we must not make this
+ an assert, as we wouldn't gracefully handle an (invalid)
+ duplicate insn description. */
+ 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
{
int bit_nr;
if (l == NULL && r == NULL)
- return 0; /* all previous fields the same */
+ return 0; /* all previous fields the same */
if (l == NULL)
- return -1; /* left shorter than right */
+ 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++)
+ return +1; /* left longer than right */
+ for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
{
if (l->bit[bit_nr]->mask < r->bit[bit_nr]->mask)
return -1;
}
}
+/* same as strcmp */
static int
-opcode_bit_cmp (opcode_bits *l,
- opcode_bits *r)
+opcode_bit_cmp (opcode_bits *l, opcode_bits *r)
{
if (l == NULL && r == NULL)
- return 0; /* all previous bits the same */
+ return 0; /* all previous bits the same */
if (l == NULL)
- return -1; /* left shorter than right */
+ return -1; /* left shorter than right */
if (r == NULL)
- return +1; /* left longer than right */
+ return +1; /* left longer than right */
/* most significant word */
if (l->field->word_nr < r->field->word_nr)
- return +1; /* left has more significant word */
+ return +1; /* left has more significant word */
if (l->field->word_nr > r->field->word_nr)
- return -1; /* right has more significant word */
+ return -1; /* right has more significant word */
/* most significant bit? */
if (l->first < r->first)
- return +1; /* left as more significant bit */
+ return +1; /* left as more significant bit */
if (l->first > r->first)
- return -1; /* right as more significant bit */
+ return -1; /* right as more significant bit */
/* nr bits? */
if (l->last < r->last)
- return +1; /* left as less bits */
+ return +1; /* left as less bits */
if (l->last > r->last)
- return -1; /* right as less bits */
+ return -1; /* right as less bits */
/* value? */
if (l->value < r->value)
return -1;
return 0;
}
+
+/* same as strcmp */
static int
-opcode_bits_cmp (opcode_bits *l,
- opcode_bits *r)
+opcode_bits_cmp (opcode_bits *l, opcode_bits *r)
{
while (1)
{
int cmp;
if (l == NULL && r == NULL)
- return 0; /* all previous bits the same */
+ return 0; /* all previous bits the same */
cmp = opcode_bit_cmp (l, r);
if (cmp != 0)
return cmp;
}
}
+/* same as strcmp */
static opcode_bits *
new_opcode_bits (opcode_bits *old_bits,
int value,
int first,
- int last,
- insn_field_entry *field,
- opcode_field *opcode)
+ int last, insn_field_entry *field, opcode_field *opcode)
{
opcode_bits *new_bits = ZALLOC (opcode_bits);
new_bits->field = field;
new_bits->first = first;
new_bits->last = last;
new_bits->opcode = opcode;
-
+
if (old_bits != NULL)
{
opcode_bits *new_list;
old_bits->value,
old_bits->first,
old_bits->last,
- old_bits->field,
- old_bits->opcode);
+ old_bits->field, old_bits->opcode);
while (*last != NULL)
{
int cmp = opcode_bit_cmp (new_bits, *last);
- if (cmp < 0) /* new < new_list */
+ if (cmp < 0) /* new < new_list */
{
break;
}
}
}
+/* Same as strcmp(). */
+static int
+name_cmp (const char *l, const char *r)
+{
+ if (l == NULL && r == NULL)
+ return 0;
+ if (l != NULL && r == NULL)
+ return -1;
+ if (l == NULL && r != NULL)
+ return +1;
+ return strcmp (l, r);
+}
-
-typedef enum {
+typedef enum
+{
merge_duplicate_insns,
report_duplicate_insns,
-} duplicate_insn_actions;
+}
+duplicate_insn_actions;
static insn_list *
insn_list_insert (insn_list **cur_insn_ptr,
int *nr_insns,
- insn_entry *insn,
+ insn_entry * insn,
opcode_bits *expanded_bits,
opcode_field *opcodes,
int nr_prefetched_words,
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)
+ 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 (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 (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;
+
+ if (duplicate_action == merge_duplicate_insns)
{
- /* found insertion point - new_insn < cur_insn->next */
- break;
+ /* key#4: If we're going to merge duplicates, also sort
+ according to the format_name. Two instructions with
+ identical decode patterns, but different names, are
+ considered different when merging. Duplicates are only
+ important when creating a decode table (implied by
+ report_duplicate_insns) as such a table only has the
+ instruction's bit code as a way of differentiating
+ between instructions. */
+ int cmp = name_cmp (insn->format_name,
+ (*cur_insn_ptr)->insn->format_name);
+ if (cmp < 0)
+ break;
+ else if (cmp > 0)
+ continue;
}
- else if (word_cmp == 0)
+
+ if (duplicate_action == merge_duplicate_insns)
{
- /* words same, try for bit fields */
- int bit_cmp = opcode_bits_cmp (expanded_bits,
- (*cur_insn_ptr)->expanded_bits);
- if (bit_cmp < 0)
+ /* key#5: If we're going to merge duplicates, also sort
+ according to the name. See comment above for
+ format_name. */
+ int cmp = name_cmp (insn->name, (*cur_insn_ptr)->insn->name);
+ if (cmp < 0)
+ break;
+ else if (cmp > 0)
+ continue;
+ }
+
+ /* duplicate keys, report problem */
+ switch (duplicate_action)
+ {
+ case report_duplicate_insns:
+ /* It would appear that we have two instructions with the
+ same constant field values across all words and bits.
+ This error can also occure when insn_field_cmp() is
+ failing to differentiate between two instructions that
+ differ only in their conditional fields. */
+ warning (insn->line,
+ "Two instructions with identical constant fields\n");
+ error ((*cur_insn_ptr)->insn->line,
+ "Location of duplicate instruction\n");
+ case merge_duplicate_insns:
+ /* Add the opcode path to the instructions list */
+ if (options.trace.insn_insertion)
{
- /* found insertion point - new_insn < cur_insn->next */
- break;
+ notify ((*cur_insn_ptr)->insn->line,
+ "%s.%s: insert merge %s.%s\n",
+ (*cur_insn_ptr)->insn->format_name,
+ (*cur_insn_ptr)->insn->name,
+ insn->format_name,
+ insn->name);
}
- else if (bit_cmp == 0)
+ if (opcodes != NULL)
{
- switch (duplicate_action)
+ insn_opcodes **last = &(*cur_insn_ptr)->opcodes;
+ while (*last != NULL)
{
- case report_duplicate_insns:
- /* two instructions with the same constant field
- values across all words and bits */
- warning (insn->line,
- "Location of second (duplicated?) instruction");
- error ((*cur_insn_ptr)->insn->line,
- "Two instructions with identical constant fields\n");
- case merge_duplicate_insns:
- /* Add the opcode path to the instructions list */
- if (opcodes != NULL)
- {
- insn_opcodes **last = &(*cur_insn_ptr)->opcodes;
- while (*last != NULL)
- {
- last = &(*last)->next;
- }
- (*last) = ZALLOC (insn_opcodes);
- (*last)->opcode = opcodes;
- }
- /* Use the larger nr_prefetched_words */
- if ((*cur_insn_ptr)->nr_prefetched_words < nr_prefetched_words)
- (*cur_insn_ptr)->nr_prefetched_words = nr_prefetched_words;
- return (*cur_insn_ptr);
+ last = &(*last)->next;
}
+ (*last) = ZALLOC (insn_opcodes);
+ (*last)->opcode = opcodes;
}
+ /* Use the larger nr_prefetched_words */
+ if ((*cur_insn_ptr)->nr_prefetched_words < nr_prefetched_words)
+ (*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 */
{
insn_list *new_insn = ZALLOC (insn_list);
+ if (options.trace.insn_insertion)
+ {
+ notify (insn->line,
+ "%s.%s: insert new\n",
+ insn->format_name,
+ insn->name);
+ }
new_insn->insn = insn;
new_insn->expanded_bits = expanded_bits;
new_insn->next = (*cur_insn_ptr);
}
(*cur_insn_ptr) = new_insn;
}
-
+
*nr_insns += 1;
return (*cur_insn_ptr);
gen_entry_traverse_tree (lf *file,
gen_entry *table,
int depth,
- gen_entry_handler *start,
- gen_entry_handler *leaf,
- gen_entry_handler *end,
- void *data)
+ gen_entry_handler * start,
+ gen_entry_handler * leaf,
+ gen_entry_handler * end, void *data)
{
gen_entry *entry;
-
- ASSERT (table != NULL);
+
+ ASSERT (table !=NULL);
ASSERT (table->opcode != NULL);
ASSERT (table->nr_entries > 0);
ASSERT (table->entries != 0);
-
+
/* prefix */
if (start != NULL && depth >= 0)
{
start (file, table, depth, data);
}
/* infix leaves */
- for (entry = table->entries;
- entry != NULL;
- entry = entry->sibling)
+ for (entry = table->entries; entry != NULL; entry = entry->sibling)
{
if (entry->entries != NULL && depth != 0)
{
/* create a list element containing a single gen_table entry */
static gen_list *
-make_table (insn_table *isa,
- decode_table *rules,
- char *processor)
+make_table (insn_table *isa, decode_table *rules, model_entry *model)
{
insn_entry *insn;
gen_list *entry = ZALLOC (gen_list);
entry->table = ZALLOC (gen_entry);
entry->table->top = entry;
- entry->processor = processor;
+ entry->model = model;
entry->isa = isa;
for (insn = isa->insns; insn != NULL; insn = insn->next)
{
- if (processor == NULL
+ if (model == NULL
|| insn->processors == NULL
- || filter_is_member (insn->processors, processor))
+ || filter_is_member (insn->processors, model->name))
{
- insn_list_insert (&entry->table->insns,
- &entry->table->nr_insns,
- insn,
- NULL, /* expanded_bits - none yet */
- NULL, /* opcodes - none yet */
- 0, /* nr_prefetched_words - none yet */
+ insn_list_insert (&entry->table->insns, &entry->table->nr_insns, insn, NULL, /* expanded_bits - none yet */
+ NULL, /* opcodes - none yet */
+ 0, /* nr_prefetched_words - none yet */
report_duplicate_insns);
}
}
gen_table *
-make_gen_tables (insn_table *isa,
- decode_table *rules)
+make_gen_tables (insn_table *isa, decode_table *rules)
{
gen_table *gen = ZALLOC (gen_table);
gen->isa = isa;
if (options.gen.multi_sim)
{
gen_list **last = &gen->tables;
- char *processor;
+ model_entry *model;
filter *processors;
if (options.model_filter != NULL)
processors = options.model_filter;
else
processors = isa->model->processors;
- for (processor = filter_next (processors, "");
- processor != NULL;
- processor = filter_next (processors, processor))
+ for (model = isa->model->models; model != NULL; model = model->next)
{
- *last = make_table (isa, rules, processor);
- last = &(*last)->next;
+ if (filter_is_member (processors, model->name))
+ {
+ *last = make_table (isa, rules, model);
+ last = &(*last)->next;
+ }
}
}
else
}
return gen;
}
-
-
-/****************************************************************/
-
-#if 0
-typedef enum {
- field_is_not_constant = 0,
- field_constant_int = 1,
- field_constant_reserved = 2,
- field_constant_string = 3
-} constant_field_types;
-
-static constant_field_types
-insn_field_is_constant (insn_field *field,
- decode_table *rule)
-{
- switch (field->type)
- {
- case insn_field_int:
- /* field is an integer */
- return field_constant_int;
- case insn_field_reserved:
- /* field is `/' and treating that as a constant */
- if (rule->with_zero_reserved)
- return field_constant_reserved;
- else
- return field_is_not_constant;
- case insn_field_wild:
- return field_is_not_constant; /* never constant */
- case insn_field_string:
- /* field, though variable, is on the list of forced constants */
- if (filter_is_member (rule->constant_field_names, field->val_string))
- return field_constant_string;
- else
- return field_is_not_constant;
- }
- ERROR ("Internal error");
- return field_is_not_constant;
-}
-#endif
/****************************************************************/
-
/* Is the bit, according to the decode rule, identical across all the
instructions? */
static int
-insns_bit_useless (insn_list *insns,
- decode_table *rule,
- int bit_nr)
+insns_bit_useless (insn_list *insns, decode_table *rule, int bit_nr)
{
insn_list *entry;
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)
{
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:
/* neither useless or useful - ignore */
case decode_find_constants:
case decode_find_mixed:
/* 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)
value = bit->value;
else if (value != bit->value)
break;
case decode_find_constants:
case decode_find_mixed:
- /* a string field forced to constant */
if (filter_is_member (rule->constant_field_names,
bit->field->val_string))
+ /* a string field forced to constant? */
is_useless = 0;
+ else if (bit->field->conditions != NULL
+ && bit->field->conditions->test == insn_field_cond_eq
+ && bit->field->conditions->type == insn_field_cond_value)
+ {
+ int shift = bit->field->last - bit_nr;
+ int bitvalue = (bit->field->conditions->value >> shift) & 1;
+
+ if (value < 0)
+ value = bitvalue;
+ else if (value != bitvalue)
+ is_useless = 0;
+ }
else if (rule->search == decode_find_constants)
/* the string field isn't constant */
return 1;
}
}
}
+
+ /* 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)
+ {
+ switch (condition->type)
+ {
+ case insn_field_cond_value:
+ switch (condition->test)
+ {
+ case insn_field_cond_ne:
+ 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)
+ != (unsigned) 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;
}
static opcode_field *
gen_entry_find_opcode_field (insn_list *insns,
- decode_table *rule,
- int string_only)
+ decode_table *rule, int string_only)
{
opcode_field curr_opcode;
ASSERT (rule != NULL);
while (curr_opcode.first <= rule->last)
{
if (insns_bit_useless (insns, rule, curr_opcode.first))
- curr_opcode.first ++;
+ curr_opcode.first++;
else
break;
}
while (curr_opcode.last >= rule->first)
{
if (insns_bit_useless (insns, rule, curr_opcode.last))
- curr_opcode.last --;
+ curr_opcode.last--;
else
break;
}
-
-#if 0
- for (entry = insns; entry != NULL; entry = entry->next)
- {
- insn_word_entry *fields = entry->insn->word[rule->word_nr];
- opcode_field new_opcode;
-
- ASSERT (fields != NULL);
-
- /* find a start point for the opcode field */
- new_opcode.first = rule->first;
- while (new_opcode.first <= rule->last
- && (!string_only
- || (insn_field_is_constant(fields->bit[new_opcode.first], rule)
- != field_constant_string))
- && (string_only
- || (insn_field_is_constant(fields->bit[new_opcode.first], rule)
- == field_is_not_constant)))
- {
- int new_first = fields->bit[new_opcode.first]->last + 1;
- ASSERT (new_first > new_opcode.first);
- new_opcode.first = new_first;
- }
- ASSERT(new_opcode.first > rule->last
- || (string_only
- && insn_field_is_constant(fields->bit[new_opcode.first],
- rule) == field_constant_string)
- || (!string_only
- && insn_field_is_constant(fields->bit[new_opcode.first],
- rule)));
-
- /* find the end point for the opcode field */
- new_opcode.last = rule->last;
- while (new_opcode.last >= rule->first
- && (!string_only
- || insn_field_is_constant(fields->bit[new_opcode.last],
- rule) != field_constant_string)
- && (string_only
- || !insn_field_is_constant(fields->bit[new_opcode.last],
- rule)))
- {
- int new_last = fields->bit[new_opcode.last]->first - 1;
- ASSERT (new_last < new_opcode.last);
- new_opcode.last = new_last;
- }
- ASSERT(new_opcode.last < rule->first
- || (string_only
- && insn_field_is_constant(fields->bit[new_opcode.last],
- rule) == field_constant_string)
- || (!string_only
- && insn_field_is_constant(fields->bit[new_opcode.last],
- rule)));
-
- /* now see if our current opcode needs expanding to include the
- interesting fields within this instruction */
- if (new_opcode.first <= rule->last
- && curr_opcode.first > new_opcode.first)
- curr_opcode.first = new_opcode.first;
- if (new_opcode.last >= rule->first
- && curr_opcode.last < new_opcode.last)
- curr_opcode.last = new_opcode.last;
-
- }
-#endif
-
/* did the final opcode field end up being empty? */
if (curr_opcode.first > curr_opcode.last)
{
/* Ensure that, for the non string only case, the opcode includes
the range forced_first .. forced_last */
- if (!string_only
- && curr_opcode.first > rule->force_first)
+ if (!string_only && curr_opcode.first > rule->force_first)
{
curr_opcode.first = rule->force_first;
}
- if (!string_only
- && curr_opcode.last < rule->force_last)
+ if (!string_only && curr_opcode.last < rule->force_last)
{
curr_opcode.last = rule->force_last;
}
/* For the string only case, force just the lower bound (so that the
shift can be eliminated) */
- if (string_only
- && rule->force_last == options.insn_bit_size - 1)
+ if (string_only && rule->force_last == options.insn_bit_size - 1)
{
curr_opcode.last = options.insn_bit_size - 1;
}
static void
gen_entry_insert_insn (gen_entry *table,
- insn_entry *old_insn,
+ insn_entry * old_insn,
int new_word_nr,
int new_nr_prefetched_words,
- int new_opcode_nr,
- opcode_bits *new_bits)
+ int new_opcode_nr, opcode_bits *new_bits)
{
gen_entry **entry = &table->entries;
-
+
/* find the new table for this entry */
while ((*entry) != NULL && (*entry)->opcode_nr < new_opcode_nr)
{
entry = &(*entry)->sibling;
}
-
+
if ((*entry) == NULL || (*entry)->opcode_nr != new_opcode_nr)
{
/* insert the missing entry */
}
/* ASSERT new_bits == cur_entry bits */
ASSERT ((*entry) != NULL && (*entry)->opcode_nr == new_opcode_nr);
- insn_list_insert (&(*entry)->insns,
- &(*entry)->nr_insns,
- old_insn,
- NULL, /* expanded_bits - only in final list */
- NULL, /* opcodes - only in final list */
- new_nr_prefetched_words, /* for this table */
+ insn_list_insert (&(*entry)->insns, &(*entry)->nr_insns, old_insn, NULL, /* expanded_bits - only in final list */
+ NULL, /* opcodes - only in final list */
+ new_nr_prefetched_words, /* for this table */
report_duplicate_insns);
}
static void
gen_entry_expand_opcode (gen_entry *table,
- insn_entry *instruction,
- int bit_nr,
- int opcode_nr,
- opcode_bits *bits)
+ insn_entry * instruction,
+ int bit_nr, int opcode_nr, opcode_bits *bits)
{
if (bit_nr > table->opcode->last)
{
/* Only include the hardwired bit information with an entry IF
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)
{
gen_entry_insert_insn (table, instruction,
table->opcode->word_nr,
- table->nr_prefetched_words,
- opcode_nr, bits);
+ table->nr_prefetched_words, opcode_nr, bits);
}
else
{
gen_entry_insert_insn (table, instruction,
table->opcode->word_nr,
- table->nr_prefetched_words,
- opcode_nr, NULL);
+ table->nr_prefetched_words, opcode_nr, NULL);
}
}
else
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),
- bits);
+ ((opcode_nr << width) | val), bits);
break;
}
default:
if (field->type == insn_field_reserved)
gen_entry_expand_opcode (table, instruction,
last_pos + 1,
- ((opcode_nr << width)),
- bits);
+ ((opcode_nr << width)), bits);
else
{
int val;
- int last_val = (table->opcode->is_boolean
- ? 2 : (1 << width));
+ int last_val = (table->opcode->is_boolean ? 2 : (1 << width));
for (val = 0; val < last_val; val++)
{
- /* check to see if the value has been limited */
- insn_field_exclusion *exclusion;
- for (exclusion = field->exclusions;
- exclusion != NULL;
- exclusion = exclusion->next)
+ /* check to see if the value has been precluded
+ (by a conditional) in some way */
+ int is_precluded;
+ insn_field_cond *condition;
+ for (condition = field->conditions, is_precluded = 0;
+ condition != NULL && !is_precluded;
+ condition = condition->next)
{
- int value = sub_val (exclusion->value, field,
- first_pos, last_pos);
- if (value == val)
- break;
+ switch (condition->type)
+ {
+ case insn_field_cond_value:
+ {
+ int value =
+ sub_val (condition->value, field->last,
+ 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 = -1;
+ opcode_bits *bit;
+ gen_entry *t = NULL;
+ /* Try to find a value for the
+ conditional by looking back through
+ the previously defined bits for one
+ that covers the designated
+ conditional field */
+ for (bit = bits; bit != NULL; bit = bit->next)
+ {
+ if (bit->field->word_nr ==
+ condition->field->word_nr
+ && bit->first <= condition->field->first
+ && bit->last >= condition->field->last)
+ {
+ /* the bit field fully specified
+ the conditional field's value */
+ value = sub_val (bit->value, bit->last,
+ condition->field->
+ first,
+ condition->field->
+ last);
+ }
+ }
+ /* 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
+ && t->parent->opcode->first <=
+ condition->field->first
+ && t->parent->opcode->last >=
+ condition->field->last)
+ {
+ /* the table entry fully
+ specified the condition
+ field's value */
+ /* extract the field's value
+ from the opcode */
+ value =
+ sub_val (t->opcode_nr,
+ t->parent->opcode->last,
+ condition->field->first,
+ condition->field->last);
+ /* this is a requirement of
+ a conditonal field
+ refering to another field */
+ ASSERT ((condition->field->first -
+ condition->field->last) ==
+ (first_pos - last_pos));
+ printf
+ ("value=%d, opcode_nr=%d, last=%d, [%d..%d]\n",
+ value, t->opcode_nr,
+ t->parent->opcode->last,
+ condition->field->first,
+ condition->field->last);
+ }
+ }
+ }
+ if (bit == NULL && t == NULL)
+ error (instruction->line,
+ "Conditional `%s' of field `%s' isn't expanded",
+ condition->string, field->val_string);
+ 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
- information if the entry is not going to
- later be combined */
+ information if the entry is not going to
+ later be combined */
if (table->opcode_rule->with_combine)
{
gen_entry_expand_opcode (table, instruction,
last_pos + 1,
- ((opcode_nr << width) | val),
- bits);
+ ((opcode_nr << width) |
+ val), bits);
}
else
{
- opcode_bits *new_bits = new_opcode_bits (bits, val,
- first_pos, last_pos,
- field,
- table->opcode);
+ opcode_bits *new_bits =
+ new_opcode_bits (bits, val,
+ first_pos, last_pos,
+ field,
+ table->opcode);
gen_entry_expand_opcode (table, instruction,
last_pos + 1,
- ((opcode_nr << width) | val),
- new_bits);
+ ((opcode_nr << width) |
+ val), new_bits);
}
}
}
}
static void
-gen_entry_insert_expanding (gen_entry *table,
- insn_entry *instruction)
+gen_entry_insert_expanding (gen_entry *table, insn_entry * instruction)
{
gen_entry_expand_opcode (table,
instruction,
- table->opcode->first,
- 0,
- table->expanded_bits);
+ table->opcode->first, 0, table->expanded_bits);
}
static int
-insns_match_format_names (insn_list *insns,
- filter *format_names)
+insns_match_format_names (insn_list *insns, filter *format_names)
{
if (format_names != NULL)
{
insn_list *i;
for (i = insns; i != NULL; i = i->next)
{
- if ( i->insn->format_name != NULL
- && !filter_is_member (format_names, i->insn->format_name))
+ if (i->insn->format_name != NULL
+ && !filter_is_member (format_names, i->insn->format_name))
return 0;
}
}
}
static int
-table_matches_path (gen_entry *table,
- decode_path_list *paths)
+table_matches_path (gen_entry *table, decode_path_list *paths)
{
if (paths == NULL)
return 1;
static int
-insns_match_conditions (insn_list *insns,
- decode_cond *conditions)
+insns_match_conditions (insn_list *insns, decode_cond *conditions)
{
if (conditions != NULL)
{
if (!i->insn->word[cond->word_nr]->bit[bit_nr]->mask)
return 0;
if ((i->insn->word[cond->word_nr]->bit[bit_nr]->value
- == cond->value[bit_nr])
- == !cond->is_equal)
+ == cond->value[bit_nr]) == !cond->is_equal)
return 0;
}
}
}
static int
-insns_match_nr_words (insn_list *insns,
- int nr_words)
+insns_match_nr_words (insn_list *insns, int nr_words)
{
insn_list *i;
for (i = insns; i != NULL; i = i->next)
}
static int
-insn_list_cmp (insn_list *l,
- insn_list *r)
+insn_list_cmp (insn_list *l, insn_list *r)
{
while (1)
{
if (r == NULL)
return 1;
if (l->insn != r->insn)
- return -1; /* somewhat arbitrary at present */
+ return -1; /* somewhat arbitrary at present */
/* skip this insn */
insn = l->insn;
while (l != NULL && l->insn == insn)
{
decode_table *opcode_rule;
- ASSERT(table->nr_insns >= 1);
-
+ ASSERT (table->nr_insns >= 1);
+
/* determine a valid opcode */
for (opcode_rule = table->opcode_rule;
- opcode_rule != NULL;
- opcode_rule = opcode_rule->next)
+ opcode_rule != NULL; opcode_rule = opcode_rule->next)
{
char *discard_reason;
- if (table->top->processor != NULL
+ if (table->top->model != NULL
&& opcode_rule->model_names != NULL
&& !filter_is_member (opcode_rule->model_names,
- table->top->processor))
+ table->top->model->name))
{
/* the rule isn't applicable to this processor */
discard_reason = "wrong model";
else if (table->nr_insns == 1 && opcode_rule->conditions == NULL)
{
/* for safety, require a pre-codition when attempting to
- apply a rule to a single instruction */
+ apply a rule to a single instruction */
discard_reason = "need pre-condition when nr-insn == 1";
}
else if (table->nr_insns == 1 && !opcode_rule->with_duplicates)
{
/* Little point in expanding a single instruction when we're
- not duplicating the semantic functions that this table
- calls */
+ not duplicating the semantic functions that this table
+ calls */
discard_reason = "need duplication with nr-insns == 1";
}
- else if (!insns_match_format_names (table->insns, opcode_rule->format_names))
+ else
+ if (!insns_match_format_names
+ (table->insns, opcode_rule->format_names))
{
discard_reason = "wrong format name";
}
{
discard_reason = "path failed";
}
- else if (!insns_match_conditions (table->insns, opcode_rule->conditions))
+ else
+ if (!insns_match_conditions (table->insns, opcode_rule->conditions))
{
discard_reason = "condition failed";
}
else
{
discard_reason = "no opcode field";
- table->opcode =
- gen_entry_find_opcode_field (table->insns,
- opcode_rule,
- table->nr_insns == 1/*string-only*/
- );
+ table->opcode = gen_entry_find_opcode_field (table->insns,
+ opcode_rule,
+ table->nr_insns == 1 /*string-only */
+ );
if (table->opcode != NULL)
{
table->opcode_rule = opcode_rule;
notify (NULL, ": rule discarded - %s\n", discard_reason);
}
}
-
+
/* did we find anything */
if (opcode_rule == NULL)
{
this table to function */
if (table->parent == NULL)
table->nr_prefetched_words = table->opcode_rule->word_nr + 1;
- else if (table->opcode_rule->word_nr + 1 > table->parent->nr_prefetched_words)
+ else if (table->opcode_rule->word_nr + 1 >
+ table->parent->nr_prefetched_words)
table->nr_prefetched_words = table->opcode_rule->word_nr + 1;
else
table->nr_prefetched_words = table->parent->nr_prefetched_words;
/* back link what we found to its parent */
if (table->parent != NULL)
{
- ASSERT(table->parent->opcode != NULL);
+ ASSERT (table->parent->opcode != NULL);
table->opcode->parent = table->parent->opcode;
}
- /* expand the raw instructions according to the opcode */
- {
- insn_list *entry;
- for (entry = table->insns; entry != NULL; entry = entry->next)
- {
- gen_entry_insert_expanding (table, entry->insn);
- }
- }
-
+ /* report the rule being used to expand the instructions */
if (options.trace.rule_selection)
{
print_gen_entry_path (table->opcode_rule->line, table, notify);
i2target (options.hi_bit_nr, table->opcode->last),
i2target (options.hi_bit_nr, table->opcode_rule->first),
i2target (options.hi_bit_nr, table->opcode_rule->last),
- table->opcode->nr_opcodes,
- table->nr_entries);
+ table->opcode->nr_opcodes, 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 */
if (options.trace.entries)
{
insn_list *l;
print_gen_entry_path (table->opcode_rule->line, entry, notify);
notify (NULL, ": %d - entries %d -",
- entry->opcode_nr,
- entry->nr_insns);
+ entry->opcode_nr, entry->nr_insns);
for (l = entry->insns; l != NULL; l = l->next)
notify (NULL, " %s.%s", l->insn->format_name, l->insn->name);
notify (NULL, "\n");
}
}
-
+
/* perform a combine pass if needed */
if (table->opcode_rule->with_combine)
{
insn_list *l;
gen_entry *duplicate;
nr_unique++;
- print_gen_entry_path (table->opcode_rule->line, entry, notify);
- for (duplicate = entry->combined_next;
- duplicate != NULL;
+ print_gen_entry_path (table->opcode_rule->line, entry,
+ notify);
+ for (duplicate = entry->combined_next; duplicate != NULL;
duplicate = duplicate->combined_next)
{
notify (NULL, "+%d", duplicate->opcode_nr);
for (l = entry->insns; l != NULL; l = l->next)
{
notify (NULL, " %s.%s",
- l->insn->format_name,
- l->insn->name);
+ l->insn->format_name, l->insn->name);
}
notify (NULL, "\n");
}
}
print_gen_entry_path (table->opcode_rule->line, table, notify);
- notify (NULL, ": combine - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d, unique %d\n",
- table->opcode->word_nr,
- i2target (options.hi_bit_nr, table->opcode->first),
+ notify (NULL,
+ ": combine - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d, unique %d\n",
+ table->opcode->word_nr, i2target (options.hi_bit_nr,
+ table->opcode->first),
i2target (options.hi_bit_nr, table->opcode->last),
i2target (options.hi_bit_nr, table->opcode_rule->first),
i2target (options.hi_bit_nr, table->opcode_rule->last),
- table->opcode->nr_opcodes,
- table->nr_entries,
- nr_unique);
+ table->opcode->nr_opcodes, table->nr_entries, nr_unique);
}
}
-
+
/* Check that the rule did more than re-arange the order of the
instructions */
{
- gen_entry *entry;
- for (entry = table->entries; entry != NULL; entry = entry->sibling)
- {
- if (entry->combined_parent == NULL)
- {
- if (insn_list_cmp (table->insns, entry->insns) == 0)
- {
- print_gen_entry_path (table->opcode_rule->line, table, warning);
- warning (NULL, ": Applying rule just copied all instructions\n");
- print_gen_entry_insns (entry, warning, "Copied", NULL);
- error (NULL, "");
- }
- }
- }
+ gen_entry *entry;
+ for (entry = table->entries; entry != NULL; entry = entry->sibling)
+ {
+ if (entry->combined_parent == NULL)
+ {
+ if (insn_list_cmp (table->insns, entry->insns) == 0)
+ {
+ print_gen_entry_path (table->opcode_rule->line, table,
+ warning);
+ warning (NULL,
+ ": Applying rule just copied all instructions\n");
+ print_gen_entry_insns (entry, warning, "Copied", NULL);
+ error (NULL, "");
+ }
+ }
+ }
}
/* if some form of expanded table, fill in the missing dots */
if ((*entry) == NULL || (*entry)->opcode_nr != opcode_nr)
{
/* missing - insert it under our feet at *entry */
- gen_entry_insert_insn (table,
- table->top->isa->illegal_insn,
- table->opcode->word_nr,
- 0, /* nr_prefetched_words == 0 for invalid */
+ gen_entry_insert_insn (table, table->top->isa->illegal_insn, table->opcode->word_nr, 0, /* nr_prefetched_words == 0 for invalid */
opcode_nr, NULL);
ASSERT ((*entry) != NULL);
ASSERT ((*entry)->opcode_nr == opcode_nr);
opcode_nr++;
}
/* oops, will have pointed the first illegal insn back to
- its self. Fix this */
+ its self. Fix this */
if (illegals != NULL)
illegals->combined_parent = NULL;
}
expand entries that haven't been combined. */
{
gen_entry *entry;
- for (entry = table->entries; entry != NULL; entry = entry->sibling)
+ for (entry = table->entries; entry != NULL; entry = entry->sibling)
{
if (entry->combined_parent == NULL)
{
worked. */
static void
-make_gen_semantics_list (lf *file,
- gen_entry *entry,
- int depth,
- void *data)
+make_gen_semantics_list (lf *file, gen_entry *entry, int depth, void *data)
{
- gen_table *gen = (gen_table*) data;
+ gen_table *gen = (gen_table *) data;
insn_list *insn;
/* Not interested in an entrie that have been combined into some
other entry at the same level */
gen_list *entry;
for (entry = gen->tables; entry != NULL; entry = entry->next)
{
- gen_entry_traverse_tree (NULL,
- entry->table,
- 1, /* depth */
- NULL, /* start-handler */
- make_gen_semantics_list, /* leaf-handler */
- NULL, /* end-handler */
- gen); /* data */
- }
+ gen_entry_traverse_tree (NULL, entry->table, 1, /* depth */
+ NULL, /* start-handler */
+ make_gen_semantics_list, /* leaf-handler */
+ NULL, /* end-handler */
+ gen); /* data */
+ }
}
static void
dump_opcode_field (lf *file,
char *prefix,
- opcode_field *field,
- char *suffix,
- int levels)
+ opcode_field *field, char *suffix, int levels)
{
lf_printf (file, "%s(opcode_field *) 0x%lx", prefix, (long) field);
- if (levels && field != NULL) {
- lf_indent (file, +1);
- lf_printf (file, "\n(first %d)", field->first);
- lf_printf (file, "\n(last %d)", field->last);
- lf_printf (file, "\n(nr_opcodes %d)", field->nr_opcodes);
- lf_printf (file, "\n(is_boolean %d)", field->is_boolean);
- lf_printf (file, "\n(boolean_constant %d)", field->boolean_constant);
- dump_opcode_field(file, "\n(parent ", field->parent, ")", levels - 1);
- lf_indent (file, -1);
- }
+ if (levels && field != NULL)
+ {
+ lf_indent (file, +1);
+ lf_printf (file, "\n(first %d)", field->first);
+ lf_printf (file, "\n(last %d)", field->last);
+ lf_printf (file, "\n(nr_opcodes %d)", field->nr_opcodes);
+ lf_printf (file, "\n(is_boolean %d)", field->is_boolean);
+ lf_printf (file, "\n(boolean_constant %d)", field->boolean_constant);
+ dump_opcode_field (file, "\n(parent ", field->parent, ")", levels - 1);
+ lf_indent (file, -1);
+ }
lf_printf (file, "%s", suffix);
}
static void
dump_opcode_bits (lf *file,
- char *prefix,
- opcode_bits *bits,
- char *suffix,
- int levels)
+ char *prefix, opcode_bits *bits, char *suffix, int levels)
{
lf_printf (file, "%s(opcode_bits *) 0x%lx", prefix, (long) bits);
-
+
if (levels && bits != NULL)
{
lf_indent (file, +1);
static void
-dump_insn_list (lf *file,
- char *prefix,
- insn_list *entry,
- char *suffix)
+dump_insn_list (lf *file, char *prefix, insn_list *entry, char *suffix)
{
lf_printf (file, "%s(insn_list *) 0x%lx", prefix, (long) entry);
- if (entry != NULL) {
- lf_indent (file, +1);
- dump_insn_entry (file, "\n(insn ", entry->insn, ")");
- lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
- lf_indent (file, -1);
- }
+ if (entry != NULL)
+ {
+ lf_indent (file, +1);
+ dump_insn_entry (file, "\n(insn ", entry->insn, ")");
+ lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
+ lf_indent (file, -1);
+ }
lf_printf (file, "%s", suffix);
}
static void
dump_insn_word_entry_list_entries (lf *file,
- char *prefix,
- insn_list *entry,
- char *suffix)
+ char *prefix,
+ insn_list *entry, char *suffix)
{
lf_printf (file, "%s", prefix);
while (entry != NULL)
static void
dump_gen_entry (lf *file,
- char *prefix,
- gen_entry *table,
- char *suffix,
- int levels)
+ char *prefix, gen_entry *table, char *suffix, int levels)
{
lf_printf (file, "%s(gen_entry *) 0x%lx", prefix, (long) table);
- if (levels && table != NULL) {
-
- lf_indent (file, +1);
- lf_printf (file, "\n(opcode_nr %d)", table->opcode_nr);
- lf_printf (file, "\n(word_nr %d)", table->word_nr);
- dump_opcode_bits (file, "\n(expanded_bits ", table->expanded_bits, ")", -1);
- lf_printf (file, "\n(nr_insns %d)", table->nr_insns);
- dump_insn_word_entry_list_entries (file, "\n(insns ", table->insns, ")");
- dump_decode_rule (file, "\n(opcode_rule ", table->opcode_rule, ")");
- dump_opcode_field (file, "\n(opcode ", table->opcode, ")", 0);
- lf_printf (file, "\n(nr_entries %d)", table->nr_entries);
- dump_gen_entry (file, "\n(entries ", table->entries, ")", table->nr_entries);
- dump_gen_entry (file, "\n(sibling ", table->sibling, ")", levels - 1);
- dump_gen_entry (file, "\n(parent ", table->parent, ")", 0);
- lf_indent (file, -1);
- }
+ if (levels && table !=NULL)
+ {
+
+ lf_indent (file, +1);
+ lf_printf (file, "\n(opcode_nr %d)", table->opcode_nr);
+ lf_printf (file, "\n(word_nr %d)", table->word_nr);
+ dump_opcode_bits (file, "\n(expanded_bits ", table->expanded_bits, ")",
+ -1);
+ lf_printf (file, "\n(nr_insns %d)", table->nr_insns);
+ dump_insn_word_entry_list_entries (file, "\n(insns ", table->insns,
+ ")");
+ dump_decode_rule (file, "\n(opcode_rule ", table->opcode_rule, ")");
+ dump_opcode_field (file, "\n(opcode ", table->opcode, ")", 0);
+ lf_printf (file, "\n(nr_entries %d)", table->nr_entries);
+ dump_gen_entry (file, "\n(entries ", table->entries, ")",
+ table->nr_entries);
+ dump_gen_entry (file, "\n(sibling ", table->sibling, ")", levels - 1);
+ dump_gen_entry (file, "\n(parent ", table->parent, ")", 0);
+ lf_indent (file, -1);
+ }
lf_printf (file, "%s", suffix);
}
static void
dump_gen_list (lf *file,
- char *prefix,
- gen_list *entry,
- char *suffix,
- int levels)
+ char *prefix, gen_list *entry, char *suffix, int levels)
{
while (entry != NULL)
{
static void
dump_gen_table (lf *file,
- char *prefix,
- gen_table *gen,
- char *suffix,
- int levels)
+ char *prefix, gen_table *gen, char *suffix, int levels)
{
lf_printf (file, "%s(gen_table *) 0x%lx", prefix, (long) gen);
lf_printf (file, "\n(isa (insn_table *) 0x%lx)", (long) gen->isa);
igen_options options;
int
-main (int argc,
- char **argv)
+main (int argc, char **argv)
{
decode_table *decode_rules;
insn_table *instructions;
lf *l;
if (argc != 7)
- error (NULL, "Usage: insn <filter-in> <hi-bit-nr> <insn-bit-size> <widths> <decode-table> <insn-table>\n");
+ error (NULL,
+ "Usage: insn <filter-in> <hi-bit-nr> <insn-bit-size> <widths> <decode-table> <insn-table>\n");
INIT_OPTIONS (options);
filter_parse (&options.flags_filter, argv[1]);
- options.hi_bit_nr = a2i(argv[2]);
- options.insn_bit_size = a2i(argv[3]);
- options.insn_specifying_widths = a2i(argv[4]);
- ASSERT(options.hi_bit_nr < options.insn_bit_size);
+ options.hi_bit_nr = a2i (argv[2]);
+ options.insn_bit_size = a2i (argv[3]);
+ options.insn_specifying_widths = a2i (argv[4]);
+ ASSERT (options.hi_bit_nr < options.insn_bit_size);
instructions = load_insn_table (argv[6], NULL);
decode_rules = load_decode_table (argv[5]);