diff options
Diffstat (limited to 'sim/igen/ld-decode.c')
-rw-r--r-- | sim/igen/ld-decode.c | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/sim/igen/ld-decode.c b/sim/igen/ld-decode.c new file mode 100644 index 0000000..baea404 --- /dev/null +++ b/sim/igen/ld-decode.c @@ -0,0 +1,404 @@ +/* This file is part of the program psim. + + Copyright (C) 1994,1995,1996, Andrew Cagney <cagney@highland.com.au> + + 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. + + 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. + + */ + +/* load the opcode stat structure */ + +#include "misc.h" +#include "lf.h" +#include "table.h" +#include "filter.h" + +#include "igen.h" + +#include "ld-decode.h" + +#ifndef NULL +#define NULL 0 +#endif + + +static const name_map decode_type_map[] = { + { "normal", normal_decode_rule }, + { "boolean", boolean_rule }, + { NULL, normal_decode_rule }, +}; + +static const name_map decode_gen_map[] = { + { "array", array_gen }, + { "switch", switch_gen }, + { "padded-switch", padded_switch_gen }, + { "goto-switch", goto_switch_gen }, + { NULL, -1 }, +}; + +static const name_map decode_reserved_map[] = { + { "zero-reserved", 1 }, + { NULL, 0 }, +}; + +static const name_map decode_duplicates_map[] = { + { "duplicate", 1 }, + { NULL, 0 }, +}; + +static const name_map decode_combine_map[] = { + { "combine", 1 }, + { NULL, 0 }, +}; + +static const name_map decode_search_map[] = { + { "constants", decode_find_constants }, + { "mixed", decode_find_mixed }, + { "strings", decode_find_strings }, + { NULL, decode_find_mixed }, +}; + + +static void +set_bits (int bit[max_insn_bit_size], + unsigned64 value) +{ + int bit_nr; + for (bit_nr = 0; bit_nr < max_insn_bit_size; bit_nr++) + { + if (bit_nr < options.insn_bit_size) + bit[bit_nr] = (value >> (options.insn_bit_size - bit_nr - 1)) & 1; + else + bit[bit_nr] = 0; + } +} + +decode_table * +load_decode_table(char *file_name) +{ + table *file = table_open (file_name); + table_entry *entry; + decode_table *table = NULL; + decode_table **curr_rule = &table; + while ((entry = table_read (file)) != NULL) + { + char *decode_options = entry->field[decode_options_field]; + decode_table *new_rule = ZALLOC (decode_table); + if (entry->nr_fields < min_nr_decode_fields) + error (entry->line, "Missing decode table fields\n"); + new_rule->line = entry->line; + + /* the options field */ + new_rule->type = name2i (decode_options, decode_type_map); + if (options.decode.overriding_gen != NULL) + new_rule->gen = name2i (options.decode.overriding_gen, decode_gen_map); + else + new_rule->gen = name2i (decode_options, decode_gen_map); + if (new_rule->gen == padded_switch_gen + && options.decode.switch_as_goto) + new_rule->gen = goto_switch_gen; + if (options.decode.zero_reserved) + new_rule->with_zero_reserved = 1; + else + new_rule->with_zero_reserved = name2i (decode_options, decode_reserved_map); + if (options.decode.duplicate) + new_rule->with_duplicates = 1; + else + new_rule->with_duplicates = name2i (decode_options, decode_duplicates_map); + if (options.decode.combine) + new_rule->with_combine = 1; + else + new_rule->with_combine = name2i (decode_options, decode_combine_map); + if (new_rule->type == boolean_rule) + { + char *chp = decode_options; + while (*chp != '\0') + { + if (isdigit (*chp)) + { + new_rule->constant = a2i (chp); + break; + } + chp = skip_to_separator (chp, ","); + chp = skip_spaces (chp); + } + } + + /* First and last */ + if (entry->nr_fields > decode_first_field + && strlen (entry->field[decode_first_field]) > 0) + { + new_rule->first = target_a2i (options.hi_bit_nr, + entry->field[decode_first_field]); + if (new_rule->first < 0 || new_rule->first >= options.insn_bit_size) + error (new_rule->line, "First field out of range\n"); + } + else + new_rule->first = 0; + if (entry->nr_fields > decode_last_field + && strlen (entry->field[decode_last_field]) > 0) + { + new_rule->last = target_a2i (options.hi_bit_nr, + entry->field[decode_last_field]); + if (new_rule->last < 0 || new_rule->last >= options.insn_bit_size) + error (new_rule->line, "Last field out of range\n"); + } + else + new_rule->last = options.insn_bit_size - 1; + if (new_rule->first > new_rule->last) + error (new_rule->line, "First must preceed last\n"); + + /* force first/last, with default values based on first/last */ + if (entry->nr_fields > decode_force_first_field + && strlen (entry->field[decode_force_first_field]) > 0) + { + new_rule->force_first = target_a2i (options.hi_bit_nr, + entry->field[decode_force_first_field]); + if (new_rule->force_first < new_rule->first + || new_rule->force_first > new_rule->last + 1) + error (new_rule->line, "Force first out of range\n"); + } + else + new_rule->force_first = new_rule->last + 1; + if (entry->nr_fields > decode_force_last_field + && strlen (entry->field[decode_force_last_field]) > 0) + { + new_rule->force_last = target_a2i (options.hi_bit_nr, + entry->field[decode_force_last_field]); + if (new_rule->force_last > new_rule->last + || new_rule->force_last < new_rule->first - 1) + error (new_rule->line, "Force-last out of range\n"); + } + else + new_rule->force_last = new_rule->first - 1; + + /* fields to be treated as constant */ + if (entry->nr_fields > decode_constant_field_names_field) + filter_parse (&new_rule->constant_field_names, + entry->field[decode_constant_field_names_field]); + + /* applicable word nr */ + if (entry->nr_fields > decode_word_nr_field) + new_rule->word_nr = a2i (entry->field[decode_word_nr_field]); + + /* required instruction format names */ + if (entry->nr_fields > decode_format_names_field) + filter_parse (&new_rule->format_names, + entry->field[decode_format_names_field]); + + /* required processor models */ + if (entry->nr_fields > decode_model_names_field) + filter_parse (&new_rule->model_names, + entry->field[decode_model_names_field]); + + /* required paths */ + if (entry->nr_fields > decode_paths_field + && strlen (entry->field[decode_paths_field]) > 0) + { + decode_path_list **last = &new_rule->paths; + char *chp = entry->field[decode_paths_field]; + do + { + (*last) = ZALLOC (decode_path_list); + /* extra root/zero entry */ + (*last)->path = ZALLOC (decode_path); + do + { + decode_path *entry = ZALLOC (decode_path); + entry->opcode_nr = a2i (chp); + entry->parent = (*last)->path; + (*last)->path = entry; + chp = skip_digits (chp); + chp = skip_spaces (chp); + } + while (*chp == '.'); + last = &(*last)->next; + } + while (*chp == ','); + if (*chp != '\0') + error (entry->line, "Invalid path field\n"); + } + + /* collect up the list of optional special conditions applicable + to the rule */ + { + int field_nr = nr_decode_fields; + while (entry->nr_fields > field_nr) + { + decode_cond *cond = ZALLOC (decode_cond); + decode_cond **last; + if (entry->nr_fields > field_nr + decode_cond_mask_field) + set_bits (cond->mask, a2i (entry->field[field_nr + decode_cond_mask_field])); + if (entry->nr_fields > field_nr + decode_cond_value_field) + { + if (entry->field[field_nr + decode_cond_value_field][0] == '!') + { + cond->is_equal = 0; + set_bits (cond->value, a2i (entry->field[field_nr + decode_cond_value_field] + 1)); + } + else + { + cond->is_equal = 1; + set_bits (cond->value, a2i (entry->field[field_nr + decode_cond_value_field])); + } + } + if (entry->nr_fields > field_nr + decode_cond_word_nr_field) + cond->word_nr = a2i (entry->field[field_nr + decode_cond_word_nr_field]); + field_nr += nr_decode_cond_fields; + /* insert it */ + last = &new_rule->conditions; + while (*last != NULL) + last = &(*last)->next; + *last = cond; + } + } + *curr_rule = new_rule; + curr_rule = &new_rule->next; + } + return table; +} + + +int +decode_table_max_word_nr (decode_table *entry) +{ + int max_word_nr = 0; + while (entry != NULL) + { + decode_cond *cond; + if (entry->word_nr > max_word_nr) + max_word_nr = entry->word_nr; + for (cond = entry->conditions; cond != NULL; cond = cond->next) + { + if (cond->word_nr > max_word_nr) + max_word_nr = cond->word_nr; + } + entry = entry->next; + } + return max_word_nr; +} + + + +static void +dump_decode_cond (lf *file, + char *prefix, + decode_cond *cond, + char *suffix) +{ + lf_printf (file, "%s(decode_cond *) 0x%lx", prefix, (long) cond); + if (cond != NULL) + { + lf_indent (file, +1); + lf_printf (file, "\n(word_nr %d)", cond->word_nr); + lf_printf (file, "\n(mask 0x%lx)", (long) cond->mask); + lf_printf (file, "\n(value 0x%lx)", (long) cond->value); + lf_printf (file, "\n(is_equal 0x%lx)", (long) cond->is_equal); + lf_printf (file, "\n(next (decode_cond *) 0%lx)", (long) cond->next); + lf_indent (file, -1); + } + lf_printf (file, "%s", suffix); +} + + +static void +dump_decode_conds (lf *file, + char *prefix, + decode_cond *cond, + char *suffix) +{ + lf_printf (file, "%s(decode_cond *) 0x%lx", prefix, (long) cond); + while (cond != NULL) + { + dump_decode_cond (file, "\n(", cond, ")"); + cond = cond->next; + } + lf_printf (file, "%s", suffix); +} + + +void +dump_decode_rule (lf *file, + char *prefix, + decode_table *rule, + char *suffix) +{ + lf_printf (file, "%s(decode_table *) 0x%lx", prefix, (long) rule); + if (rule != NULL) + { + lf_indent (file, +1); + dump_line_ref (file, "\n(line ", rule->line, ")"); + lf_printf (file, "\n(type %s)", i2name(rule->type, decode_type_map)); + lf_printf (file, "\n(gen %s)", i2name(rule->gen, decode_gen_map)); + lf_printf (file, "\n(first %d)", rule->first); + lf_printf (file, "\n(last %d)", rule->last); + lf_printf (file, "\n(force_first %d)", rule->force_first); + lf_printf (file, "\n(force_last %d)", rule->force_last); + dump_filter (file, "\n(constant_field_names \"", rule->constant_field_names, "\")"); + lf_printf (file, "\n(constant 0x%x)", rule->constant); + lf_printf (file, "\n(word_nr %d)", rule->word_nr); + lf_printf (file, "\n(with_zero_reserved %d)", rule->with_zero_reserved); + lf_printf (file, "\n(with_duplicates %d)", rule->with_duplicates); + lf_printf (file, "\n(with_combine %d)", rule->with_combine); + dump_filter (file, "\n(format_names \"", rule->format_names, "\")"); + dump_filter (file, "\n(model_names \"", rule->model_names, "\")"); + dump_decode_conds (file, "\n(conditions ", rule->conditions, ")"); + lf_printf (file, "\n(next 0x%lx)", (long) rule->next); + lf_indent (file, -1); + } + lf_printf (file, "%s", suffix); +} + + +#ifdef MAIN + +static void +dump_decode_rules (lf *file, + char *prefix, + decode_table *rule, + char *suffix) +{ + lf_printf (file, "%s", prefix); + while (rule != NULL) + { + lf_indent (file, +1); + dump_decode_rule (file, "\n(", rule, ")"); + lf_indent (file, -1); + rule = rule->next; + } + lf_printf (file, "%s", suffix); +} + +igen_options options; + +int +main(int argc, char **argv) +{ + lf *l; + decode_table *rules; + + INIT_OPTIONS (options); + + if (argc != 3) + error (NULL, "Usage: decode <decode-file> <hi-bit-nr>\n"); + + options.hi_bit_nr = a2i (argv[2]); + rules = load_decode_table (argv[1]); + l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn"); + dump_decode_rules (l, "(rules ", rules, ")\n"); + + return 0; +} +#endif |