14e98e3e1Schristos /* The IGEN simulator generator for GDB, the GNU Debugger. 24e98e3e1Schristos 3*71f62182Schristos Copyright 2002-2024 Free Software Foundation, Inc. 44e98e3e1Schristos 54e98e3e1Schristos Contributed by Andrew Cagney. 64e98e3e1Schristos 74e98e3e1Schristos This file is part of GDB. 84e98e3e1Schristos 94e98e3e1Schristos This program is free software; you can redistribute it and/or modify 104e98e3e1Schristos it under the terms of the GNU General Public License as published by 114e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 124e98e3e1Schristos (at your option) any later version. 134e98e3e1Schristos 144e98e3e1Schristos This program is distributed in the hope that it will be useful, 154e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 164e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 174e98e3e1Schristos GNU General Public License for more details. 184e98e3e1Schristos 194e98e3e1Schristos You should have received a copy of the GNU General Public License 204e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 214e98e3e1Schristos 224e98e3e1Schristos 234e98e3e1Schristos /* load the opcode stat structure */ 244e98e3e1Schristos 254e98e3e1Schristos #include "misc.h" 264e98e3e1Schristos #include "lf.h" 274e98e3e1Schristos #include "table.h" 284e98e3e1Schristos #include "filter.h" 294e98e3e1Schristos 304e98e3e1Schristos #include "igen.h" 314e98e3e1Schristos 324e98e3e1Schristos #include "ld-decode.h" 334e98e3e1Schristos 344e98e3e1Schristos 354e98e3e1Schristos static const name_map decode_type_map[] = { 364e98e3e1Schristos {"normal", normal_decode_rule}, 374e98e3e1Schristos {"boolean", boolean_rule}, 384e98e3e1Schristos {NULL, normal_decode_rule}, 394e98e3e1Schristos }; 404e98e3e1Schristos 414e98e3e1Schristos static const name_map decode_gen_map[] = { 424e98e3e1Schristos {"array", array_gen}, 434e98e3e1Schristos {"switch", switch_gen}, 444e98e3e1Schristos {"padded-switch", padded_switch_gen}, 454e98e3e1Schristos {"goto-switch", goto_switch_gen}, 464e98e3e1Schristos {NULL, -1}, 474e98e3e1Schristos }; 484e98e3e1Schristos 494e98e3e1Schristos static const name_map decode_reserved_map[] = { 504e98e3e1Schristos {"zero-reserved", 1}, 514e98e3e1Schristos {NULL, 0}, 524e98e3e1Schristos }; 534e98e3e1Schristos 544e98e3e1Schristos static const name_map decode_duplicates_map[] = { 554e98e3e1Schristos {"duplicate", 1}, 564e98e3e1Schristos {NULL, 0}, 574e98e3e1Schristos }; 584e98e3e1Schristos 594e98e3e1Schristos static const name_map decode_combine_map[] = { 604e98e3e1Schristos {"combine", 1}, 614e98e3e1Schristos {NULL, 0}, 624e98e3e1Schristos }; 634e98e3e1Schristos 64*71f62182Schristos #if 0 654e98e3e1Schristos static const name_map decode_search_map[] = { 664e98e3e1Schristos {"constants", decode_find_constants}, 674e98e3e1Schristos {"mixed", decode_find_mixed}, 684e98e3e1Schristos {"strings", decode_find_strings}, 694e98e3e1Schristos {NULL, decode_find_mixed}, 704e98e3e1Schristos }; 71*71f62182Schristos #endif 724e98e3e1Schristos 734e98e3e1Schristos 744e98e3e1Schristos static void 754b169a6bSchristos set_bits (int bit[max_insn_bit_size], uint64_t value) 764e98e3e1Schristos { 774e98e3e1Schristos int bit_nr; 784e98e3e1Schristos for (bit_nr = 0; bit_nr < max_insn_bit_size; bit_nr++) 794e98e3e1Schristos { 804e98e3e1Schristos if (bit_nr < options.insn_bit_size) 814e98e3e1Schristos bit[bit_nr] = (value >> (options.insn_bit_size - bit_nr - 1)) & 1; 824e98e3e1Schristos else 834e98e3e1Schristos bit[bit_nr] = 0; 844e98e3e1Schristos } 854e98e3e1Schristos } 864e98e3e1Schristos 874e98e3e1Schristos decode_table * 884b169a6bSchristos load_decode_table (const char *file_name) 894e98e3e1Schristos { 904e98e3e1Schristos table *file = table_open (file_name); 914e98e3e1Schristos table_entry *entry; 924e98e3e1Schristos decode_table *table = NULL; 934e98e3e1Schristos decode_table **curr_rule = &table; 944e98e3e1Schristos while ((entry = table_read (file)) != NULL) 954e98e3e1Schristos { 964e98e3e1Schristos char *decode_options = entry->field[decode_options_field]; 974e98e3e1Schristos decode_table *new_rule = ZALLOC (decode_table); 984e98e3e1Schristos if (entry->nr_fields < min_nr_decode_fields) 994e98e3e1Schristos error (entry->line, "Missing decode table fields\n"); 1004e98e3e1Schristos new_rule->line = entry->line; 1014e98e3e1Schristos 1024e98e3e1Schristos /* the options field */ 1034e98e3e1Schristos new_rule->type = name2i (decode_options, decode_type_map); 1044e98e3e1Schristos if (options.decode.overriding_gen != NULL) 1054e98e3e1Schristos new_rule->gen = 1064e98e3e1Schristos name2i (options.decode.overriding_gen, decode_gen_map); 1074e98e3e1Schristos else 1084e98e3e1Schristos new_rule->gen = name2i (decode_options, decode_gen_map); 1094e98e3e1Schristos if (new_rule->gen == padded_switch_gen && options.decode.switch_as_goto) 1104e98e3e1Schristos new_rule->gen = goto_switch_gen; 1114e98e3e1Schristos if (options.decode.zero_reserved) 1124e98e3e1Schristos new_rule->with_zero_reserved = 1; 1134e98e3e1Schristos else 1144e98e3e1Schristos new_rule->with_zero_reserved = 1154e98e3e1Schristos name2i (decode_options, decode_reserved_map); 1164e98e3e1Schristos if (options.decode.duplicate) 1174e98e3e1Schristos new_rule->with_duplicates = 1; 1184e98e3e1Schristos else 1194e98e3e1Schristos new_rule->with_duplicates = 1204e98e3e1Schristos name2i (decode_options, decode_duplicates_map); 1214e98e3e1Schristos if (options.decode.combine) 1224e98e3e1Schristos new_rule->with_combine = 1; 1234e98e3e1Schristos else 1244e98e3e1Schristos new_rule->with_combine = name2i (decode_options, decode_combine_map); 1254e98e3e1Schristos if (new_rule->type == boolean_rule) 1264e98e3e1Schristos { 1274e98e3e1Schristos char *chp = decode_options; 1284e98e3e1Schristos while (*chp != '\0') 1294e98e3e1Schristos { 1304e98e3e1Schristos if (isdigit (*chp)) 1314e98e3e1Schristos { 1324e98e3e1Schristos new_rule->constant = a2i (chp); 1334e98e3e1Schristos break; 1344e98e3e1Schristos } 1354e98e3e1Schristos chp = skip_to_separator (chp, ","); 1364b169a6bSchristos if (*chp == ',') 1374b169a6bSchristos ++chp; 1384e98e3e1Schristos chp = skip_spaces (chp); 1394e98e3e1Schristos } 1404e98e3e1Schristos } 1414e98e3e1Schristos 1424e98e3e1Schristos /* First and last */ 1434e98e3e1Schristos if (entry->nr_fields > decode_first_field 1444e98e3e1Schristos && strlen (entry->field[decode_first_field]) > 0) 1454e98e3e1Schristos { 1464e98e3e1Schristos new_rule->first = target_a2i (options.hi_bit_nr, 1474e98e3e1Schristos entry->field[decode_first_field]); 1484e98e3e1Schristos if (new_rule->first < 0 || new_rule->first >= options.insn_bit_size) 1494e98e3e1Schristos error (new_rule->line, "First field out of range\n"); 1504e98e3e1Schristos } 1514e98e3e1Schristos else 1524e98e3e1Schristos new_rule->first = 0; 1534e98e3e1Schristos if (entry->nr_fields > decode_last_field 1544e98e3e1Schristos && strlen (entry->field[decode_last_field]) > 0) 1554e98e3e1Schristos { 1564e98e3e1Schristos new_rule->last = target_a2i (options.hi_bit_nr, 1574e98e3e1Schristos entry->field[decode_last_field]); 1584e98e3e1Schristos if (new_rule->last < 0 || new_rule->last >= options.insn_bit_size) 1594e98e3e1Schristos error (new_rule->line, "Last field out of range\n"); 1604e98e3e1Schristos } 1614e98e3e1Schristos else 1624e98e3e1Schristos new_rule->last = options.insn_bit_size - 1; 1634e98e3e1Schristos if (new_rule->first > new_rule->last) 1644e98e3e1Schristos error (new_rule->line, "First must preceed last\n"); 1654e98e3e1Schristos 1664e98e3e1Schristos /* force first/last, with default values based on first/last */ 1674e98e3e1Schristos if (entry->nr_fields > decode_force_first_field 1684e98e3e1Schristos && strlen (entry->field[decode_force_first_field]) > 0) 1694e98e3e1Schristos { 1704e98e3e1Schristos new_rule->force_first = target_a2i (options.hi_bit_nr, 1714e98e3e1Schristos entry-> 1724e98e3e1Schristos field 1734e98e3e1Schristos [decode_force_first_field]); 1744e98e3e1Schristos if (new_rule->force_first < new_rule->first 1754e98e3e1Schristos || new_rule->force_first > new_rule->last + 1) 1764e98e3e1Schristos error (new_rule->line, "Force first out of range\n"); 1774e98e3e1Schristos } 1784e98e3e1Schristos else 1794e98e3e1Schristos new_rule->force_first = new_rule->last + 1; 1804e98e3e1Schristos if (entry->nr_fields > decode_force_last_field 1814e98e3e1Schristos && strlen (entry->field[decode_force_last_field]) > 0) 1824e98e3e1Schristos { 1834e98e3e1Schristos new_rule->force_last = target_a2i (options.hi_bit_nr, 1844e98e3e1Schristos entry-> 1854e98e3e1Schristos field[decode_force_last_field]); 1864e98e3e1Schristos if (new_rule->force_last > new_rule->last 1874e98e3e1Schristos || new_rule->force_last < new_rule->first - 1) 1884e98e3e1Schristos error (new_rule->line, "Force-last out of range\n"); 1894e98e3e1Schristos } 1904e98e3e1Schristos else 1914e98e3e1Schristos new_rule->force_last = new_rule->first - 1; 1924e98e3e1Schristos 1934e98e3e1Schristos /* fields to be treated as constant */ 1944e98e3e1Schristos if (entry->nr_fields > decode_constant_field_names_field) 1954e98e3e1Schristos filter_parse (&new_rule->constant_field_names, 1964e98e3e1Schristos entry->field[decode_constant_field_names_field]); 1974e98e3e1Schristos 1984e98e3e1Schristos /* applicable word nr */ 1994e98e3e1Schristos if (entry->nr_fields > decode_word_nr_field) 2004e98e3e1Schristos new_rule->word_nr = a2i (entry->field[decode_word_nr_field]); 2014e98e3e1Schristos 2024e98e3e1Schristos /* required instruction format names */ 2034e98e3e1Schristos if (entry->nr_fields > decode_format_names_field) 2044e98e3e1Schristos filter_parse (&new_rule->format_names, 2054e98e3e1Schristos entry->field[decode_format_names_field]); 2064e98e3e1Schristos 2074e98e3e1Schristos /* required processor models */ 2084e98e3e1Schristos if (entry->nr_fields > decode_model_names_field) 2094e98e3e1Schristos filter_parse (&new_rule->model_names, 2104e98e3e1Schristos entry->field[decode_model_names_field]); 2114e98e3e1Schristos 2124e98e3e1Schristos /* required paths */ 2134e98e3e1Schristos if (entry->nr_fields > decode_paths_field 2144e98e3e1Schristos && strlen (entry->field[decode_paths_field]) > 0) 2154e98e3e1Schristos { 2164e98e3e1Schristos decode_path_list **last = &new_rule->paths; 2174e98e3e1Schristos char *chp = entry->field[decode_paths_field]; 2184e98e3e1Schristos do 2194e98e3e1Schristos { 2204e98e3e1Schristos (*last) = ZALLOC (decode_path_list); 2214e98e3e1Schristos /* extra root/zero entry */ 2224e98e3e1Schristos (*last)->path = ZALLOC (decode_path); 2234e98e3e1Schristos do 2244e98e3e1Schristos { 2254e98e3e1Schristos decode_path *entry = ZALLOC (decode_path); 2264e98e3e1Schristos entry->opcode_nr = a2i (chp); 2274e98e3e1Schristos entry->parent = (*last)->path; 2284e98e3e1Schristos (*last)->path = entry; 2294e98e3e1Schristos chp = skip_digits (chp); 2304e98e3e1Schristos chp = skip_spaces (chp); 2314e98e3e1Schristos } 2324e98e3e1Schristos while (*chp == '.'); 2334e98e3e1Schristos last = &(*last)->next; 2344e98e3e1Schristos } 2354e98e3e1Schristos while (*chp == ','); 2364e98e3e1Schristos if (*chp != '\0') 2374e98e3e1Schristos error (entry->line, "Invalid path field\n"); 2384e98e3e1Schristos } 2394e98e3e1Schristos 2404e98e3e1Schristos /* collect up the list of optional special conditions applicable 2414e98e3e1Schristos to the rule */ 2424e98e3e1Schristos { 2434e98e3e1Schristos int field_nr = nr_decode_fields; 2444e98e3e1Schristos while (entry->nr_fields > field_nr) 2454e98e3e1Schristos { 2464e98e3e1Schristos decode_cond *cond = ZALLOC (decode_cond); 2474e98e3e1Schristos decode_cond **last; 2484e98e3e1Schristos if (entry->nr_fields > field_nr + decode_cond_mask_field) 2494e98e3e1Schristos set_bits (cond->mask, 2504e98e3e1Schristos a2i (entry-> 2514e98e3e1Schristos field[field_nr + decode_cond_mask_field])); 2524e98e3e1Schristos if (entry->nr_fields > field_nr + decode_cond_value_field) 2534e98e3e1Schristos { 2544e98e3e1Schristos if (entry->field[field_nr + decode_cond_value_field][0] == 2554e98e3e1Schristos '!') 2564e98e3e1Schristos { 2574e98e3e1Schristos cond->is_equal = 0; 2584e98e3e1Schristos set_bits (cond->value, 2594e98e3e1Schristos a2i (entry-> 2604e98e3e1Schristos field[field_nr + decode_cond_value_field] + 2614e98e3e1Schristos 1)); 2624e98e3e1Schristos } 2634e98e3e1Schristos else 2644e98e3e1Schristos { 2654e98e3e1Schristos cond->is_equal = 1; 2664e98e3e1Schristos set_bits (cond->value, 2674e98e3e1Schristos a2i (entry-> 2684e98e3e1Schristos field[field_nr + 2694e98e3e1Schristos decode_cond_value_field])); 2704e98e3e1Schristos } 2714e98e3e1Schristos } 2724e98e3e1Schristos if (entry->nr_fields > field_nr + decode_cond_word_nr_field) 2734e98e3e1Schristos cond->word_nr = 2744e98e3e1Schristos a2i (entry->field[field_nr + decode_cond_word_nr_field]); 2754e98e3e1Schristos field_nr += nr_decode_cond_fields; 2764e98e3e1Schristos /* insert it */ 2774e98e3e1Schristos last = &new_rule->conditions; 2784e98e3e1Schristos while (*last != NULL) 2794e98e3e1Schristos last = &(*last)->next; 2804e98e3e1Schristos *last = cond; 2814e98e3e1Schristos } 2824e98e3e1Schristos } 2834e98e3e1Schristos *curr_rule = new_rule; 2844e98e3e1Schristos curr_rule = &new_rule->next; 2854e98e3e1Schristos } 2864e98e3e1Schristos return table; 2874e98e3e1Schristos } 2884e98e3e1Schristos 2894e98e3e1Schristos 2904e98e3e1Schristos int 2914b169a6bSchristos decode_table_max_word_nr (const decode_table *entry) 2924e98e3e1Schristos { 2934e98e3e1Schristos int max_word_nr = 0; 2944e98e3e1Schristos while (entry != NULL) 2954e98e3e1Schristos { 2964e98e3e1Schristos decode_cond *cond; 2974e98e3e1Schristos if (entry->word_nr > max_word_nr) 2984e98e3e1Schristos max_word_nr = entry->word_nr; 2994e98e3e1Schristos for (cond = entry->conditions; cond != NULL; cond = cond->next) 3004e98e3e1Schristos { 3014e98e3e1Schristos if (cond->word_nr > max_word_nr) 3024e98e3e1Schristos max_word_nr = cond->word_nr; 3034e98e3e1Schristos } 3044e98e3e1Schristos entry = entry->next; 3054e98e3e1Schristos } 3064e98e3e1Schristos return max_word_nr; 3074e98e3e1Schristos } 3084e98e3e1Schristos 3094e98e3e1Schristos 3104e98e3e1Schristos static void 3114b169a6bSchristos dump_decode_cond (lf *file, const char *prefix, const decode_cond *cond, 3124b169a6bSchristos const char *suffix) 3134e98e3e1Schristos { 3144b169a6bSchristos lf_printf (file, "%s(decode_cond *) %p", prefix, cond); 3154e98e3e1Schristos if (cond != NULL) 3164e98e3e1Schristos { 3174e98e3e1Schristos lf_indent (file, +1); 3184e98e3e1Schristos lf_printf (file, "\n(word_nr %d)", cond->word_nr); 3194b169a6bSchristos lf_printf (file, "\n(mask %p)", cond->mask); 3204b169a6bSchristos lf_printf (file, "\n(value %p)", cond->value); 3214b169a6bSchristos lf_printf (file, "\n(is_equal %d)", cond->is_equal); 3224b169a6bSchristos lf_printf (file, "\n(next (decode_cond *) %p)", cond->next); 3234e98e3e1Schristos lf_indent (file, -1); 3244e98e3e1Schristos } 3254e98e3e1Schristos lf_printf (file, "%s", suffix); 3264e98e3e1Schristos } 3274e98e3e1Schristos 3284e98e3e1Schristos 3294e98e3e1Schristos static void 3304b169a6bSchristos dump_decode_conds (lf *file, const char *prefix, const decode_cond *cond, 3314b169a6bSchristos const char *suffix) 3324e98e3e1Schristos { 3334b169a6bSchristos lf_printf (file, "%s(decode_cond *) %p", prefix, cond); 3344e98e3e1Schristos while (cond != NULL) 3354e98e3e1Schristos { 3364e98e3e1Schristos dump_decode_cond (file, "\n(", cond, ")"); 3374e98e3e1Schristos cond = cond->next; 3384e98e3e1Schristos } 3394e98e3e1Schristos lf_printf (file, "%s", suffix); 3404e98e3e1Schristos } 3414e98e3e1Schristos 3424e98e3e1Schristos 3434e98e3e1Schristos void 3444b169a6bSchristos dump_decode_rule (lf *file, const char *prefix, const decode_table *rule, 3454b169a6bSchristos const char *suffix) 3464e98e3e1Schristos { 3474b169a6bSchristos lf_printf (file, "%s(decode_table *) %p", prefix, rule); 3484e98e3e1Schristos if (rule != NULL) 3494e98e3e1Schristos { 3504e98e3e1Schristos lf_indent (file, +1); 3514e98e3e1Schristos dump_line_ref (file, "\n(line ", rule->line, ")"); 3524e98e3e1Schristos lf_printf (file, "\n(type %s)", i2name (rule->type, decode_type_map)); 3534e98e3e1Schristos lf_printf (file, "\n(gen %s)", i2name (rule->gen, decode_gen_map)); 3544e98e3e1Schristos lf_printf (file, "\n(first %d)", rule->first); 3554e98e3e1Schristos lf_printf (file, "\n(last %d)", rule->last); 3564e98e3e1Schristos lf_printf (file, "\n(force_first %d)", rule->force_first); 3574e98e3e1Schristos lf_printf (file, "\n(force_last %d)", rule->force_last); 3584e98e3e1Schristos dump_filter (file, "\n(constant_field_names \"", 3594e98e3e1Schristos rule->constant_field_names, "\")"); 3604e98e3e1Schristos lf_printf (file, "\n(constant 0x%x)", rule->constant); 3614e98e3e1Schristos lf_printf (file, "\n(word_nr %d)", rule->word_nr); 3624e98e3e1Schristos lf_printf (file, "\n(with_zero_reserved %d)", rule->with_zero_reserved); 3634e98e3e1Schristos lf_printf (file, "\n(with_duplicates %d)", rule->with_duplicates); 3644e98e3e1Schristos lf_printf (file, "\n(with_combine %d)", rule->with_combine); 3654e98e3e1Schristos dump_filter (file, "\n(format_names \"", rule->format_names, "\")"); 3664e98e3e1Schristos dump_filter (file, "\n(model_names \"", rule->model_names, "\")"); 3674e98e3e1Schristos dump_decode_conds (file, "\n(conditions ", rule->conditions, ")"); 3684b169a6bSchristos lf_printf (file, "\n(next %p)", rule->next); 3694e98e3e1Schristos lf_indent (file, -1); 3704e98e3e1Schristos } 3714e98e3e1Schristos lf_printf (file, "%s", suffix); 3724e98e3e1Schristos } 3734e98e3e1Schristos 3744e98e3e1Schristos 3754e98e3e1Schristos #ifdef MAIN 3764e98e3e1Schristos 3774e98e3e1Schristos static void 3784b169a6bSchristos dump_decode_rules (lf *file, 3794b169a6bSchristos const char *prefix, 3804b169a6bSchristos const decode_table *rule, 3814b169a6bSchristos const char *suffix) 3824e98e3e1Schristos { 3834e98e3e1Schristos lf_printf (file, "%s", prefix); 3844e98e3e1Schristos while (rule != NULL) 3854e98e3e1Schristos { 3864e98e3e1Schristos lf_indent (file, +1); 3874e98e3e1Schristos dump_decode_rule (file, "\n(", rule, ")"); 3884e98e3e1Schristos lf_indent (file, -1); 3894e98e3e1Schristos rule = rule->next; 3904e98e3e1Schristos } 3914e98e3e1Schristos lf_printf (file, "%s", suffix); 3924e98e3e1Schristos } 3934e98e3e1Schristos 3944e98e3e1Schristos igen_options options; 3954e98e3e1Schristos 3964e98e3e1Schristos int 3974e98e3e1Schristos main (int argc, char **argv) 3984e98e3e1Schristos { 3994e98e3e1Schristos lf *l; 4004e98e3e1Schristos decode_table *rules; 4014e98e3e1Schristos 4024b169a6bSchristos INIT_OPTIONS (); 4034e98e3e1Schristos 4044e98e3e1Schristos if (argc != 3) 4054e98e3e1Schristos error (NULL, "Usage: decode <decode-file> <hi-bit-nr>\n"); 4064e98e3e1Schristos 4074e98e3e1Schristos options.hi_bit_nr = a2i (argv[2]); 4084e98e3e1Schristos rules = load_decode_table (argv[1]); 4094e98e3e1Schristos l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn"); 4104e98e3e1Schristos dump_decode_rules (l, "(rules ", rules, ")\n"); 4114e98e3e1Schristos 4124e98e3e1Schristos return 0; 4134e98e3e1Schristos } 4144e98e3e1Schristos #endif 415