/* The IGEN simulator generator for GDB, the GNU Debugger.
- Copyright 2002 Free Software Foundation, Inc.
+ Copyright 2002-2015 Free Software Foundation, Inc.
Contributed by Andrew Cagney.
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
+ 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,
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. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "misc.h"
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. */
+ 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)
/* Same as strcmp(). */
static int
-format_name_cmp (const char *l, const char *r)
+name_cmp (const char *l, const char *r)
{
if (l == NULL && r == NULL)
return 0;
else if (cmp > 0)
continue;
- /* key#4 sort according to the format-name. If two apparently
- identical instructions have unique format-names, then the
- instructions are different. This is because the
- format-name's use is overloaded, it not only indicates the
- format name but also provides a unique semantic name for the
- function. */
- cmp =
- format_name_cmp (insn->format_name,
- (*cur_insn_ptr)->insn->format_name);
- if (cmp < 0)
- break;
- else if (cmp > 0)
- continue;
+ if (duplicate_action == merge_duplicate_insns)
+ {
+ /* 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;
+ }
+
+ if (duplicate_action == merge_duplicate_insns)
+ {
+ /* 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)
"Location of duplicate instruction\n");
case merge_duplicate_insns:
/* Add the opcode path to the instructions list */
+ if (options.trace.insn_insertion)
+ {
+ 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);
+ }
if (opcodes != NULL)
{
insn_opcodes **last = &(*cur_insn_ptr)->opcodes;
/* 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);
/****************************************************************/
-#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
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;
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)
{