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 #include "misc.h" 244e98e3e1Schristos #include "lf.h" 254e98e3e1Schristos #include "table.h" 264e98e3e1Schristos #include "filter.h" 274e98e3e1Schristos 284e98e3e1Schristos #include "igen.h" 294e98e3e1Schristos #include "ld-insn.h" 304e98e3e1Schristos #include "ld-decode.h" 314e98e3e1Schristos #include "gen.h" 324e98e3e1Schristos 334e98e3e1Schristos static insn_uint 344e98e3e1Schristos sub_val (insn_uint val, int val_last_pos, int first_pos, int last_pos) 354e98e3e1Schristos { 364e98e3e1Schristos return ((val >> (val_last_pos - last_pos)) 374e98e3e1Schristos & (((insn_uint) 1 << (last_pos - first_pos + 1)) - 1)); 384e98e3e1Schristos } 394e98e3e1Schristos 404e98e3e1Schristos static void 414b169a6bSchristos update_depth (lf *file, const gen_entry *entry, int depth, void *data) 424e98e3e1Schristos { 434e98e3e1Schristos int *max_depth = (int *) data; 444e98e3e1Schristos if (*max_depth < depth) 454e98e3e1Schristos *max_depth = depth; 464e98e3e1Schristos } 474e98e3e1Schristos 484e98e3e1Schristos 494e98e3e1Schristos int 504b169a6bSchristos gen_entry_depth (const gen_entry *table) 514e98e3e1Schristos { 524e98e3e1Schristos int depth = 0; 534e98e3e1Schristos gen_entry_traverse_tree (NULL, table, 1, NULL, /*start */ 544e98e3e1Schristos update_depth, NULL, /*end */ 554e98e3e1Schristos &depth); /* data */ 564e98e3e1Schristos return depth; 574e98e3e1Schristos } 584e98e3e1Schristos 594e98e3e1Schristos 604e98e3e1Schristos static void 614b169a6bSchristos print_gen_entry_path (const line_ref *line, 624b169a6bSchristos const gen_entry *table, 634b169a6bSchristos error_func *print) 644e98e3e1Schristos { 654e98e3e1Schristos if (table->parent == NULL) 664e98e3e1Schristos { 674e98e3e1Schristos if (table->top->model != NULL) 684e98e3e1Schristos print (line, "%s", table->top->model->name); 694e98e3e1Schristos else 70*71f62182Schristos { 71*71f62182Schristos /* We don't want to output things, but we want the side-effects they 72*71f62182Schristos might have (e.g. checking line != NULL). */ 73*71f62182Schristos print (line, "%s", ""); 74*71f62182Schristos } 754e98e3e1Schristos } 764e98e3e1Schristos else 774e98e3e1Schristos { 784e98e3e1Schristos print_gen_entry_path (line, table->parent, print); 794e98e3e1Schristos print (NULL, ".%d", table->opcode_nr); 804e98e3e1Schristos } 814e98e3e1Schristos } 824e98e3e1Schristos 834e98e3e1Schristos static void 844b169a6bSchristos print_gen_entry_insns (const gen_entry *table, 854e98e3e1Schristos error_func *print, 864b169a6bSchristos const char *first_message, 874b169a6bSchristos const char *next_message) 884e98e3e1Schristos { 894e98e3e1Schristos insn_list *i; 904b169a6bSchristos const char *message; 914e98e3e1Schristos message = first_message; 924e98e3e1Schristos for (i = table->insns; i != NULL; i = i->next) 934e98e3e1Schristos { 944e98e3e1Schristos insn_entry *insn = i->insn; 954e98e3e1Schristos print_gen_entry_path (insn->line, table, print); 964e98e3e1Schristos print (NULL, ": %s.%s %s\n", insn->format_name, insn->name, message); 974e98e3e1Schristos if (next_message != NULL) 984e98e3e1Schristos message = next_message; 994e98e3e1Schristos } 1004e98e3e1Schristos } 1014e98e3e1Schristos 1024e98e3e1Schristos /* same as strcmp */ 1034e98e3e1Schristos static int 1044b169a6bSchristos insn_field_cmp (const insn_word_entry *l, const insn_word_entry *r) 1054e98e3e1Schristos { 1064e98e3e1Schristos while (1) 1074e98e3e1Schristos { 1084e98e3e1Schristos int bit_nr; 1094e98e3e1Schristos if (l == NULL && r == NULL) 1104e98e3e1Schristos return 0; /* all previous fields the same */ 1114e98e3e1Schristos if (l == NULL) 1124e98e3e1Schristos return -1; /* left shorter than right */ 1134e98e3e1Schristos if (r == NULL) 1144e98e3e1Schristos return +1; /* left longer than right */ 1154e98e3e1Schristos for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++) 1164e98e3e1Schristos { 1174e98e3e1Schristos if (l->bit[bit_nr]->field->type != insn_field_string) 1184e98e3e1Schristos continue; 1194e98e3e1Schristos if (r->bit[bit_nr]->field->type != insn_field_string) 1204e98e3e1Schristos continue; 1214e98e3e1Schristos if (l->bit[bit_nr]->field->conditions == NULL) 1224e98e3e1Schristos continue; 1234e98e3e1Schristos if (r->bit[bit_nr]->field->conditions == NULL) 1244e98e3e1Schristos continue; 1254e98e3e1Schristos if (0) 1264e98e3e1Schristos printf ("%s%s%s VS %s%s%s\n", 1274e98e3e1Schristos l->bit[bit_nr]->field->val_string, 1284e98e3e1Schristos l->bit[bit_nr]->field->conditions->test == 1294e98e3e1Schristos insn_field_cond_eq ? "=" : "!", 1304e98e3e1Schristos l->bit[bit_nr]->field->conditions->string, 1314e98e3e1Schristos r->bit[bit_nr]->field->val_string, 1324e98e3e1Schristos r->bit[bit_nr]->field->conditions->test == 1334e98e3e1Schristos insn_field_cond_eq ? "=" : "!", 1344e98e3e1Schristos r->bit[bit_nr]->field->conditions->string); 1354e98e3e1Schristos if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq 1364e98e3e1Schristos && r->bit[bit_nr]->field->conditions->test == 1374e98e3e1Schristos insn_field_cond_eq) 1384e98e3e1Schristos { 1394e98e3e1Schristos if (l->bit[bit_nr]->field->conditions->type == 1404e98e3e1Schristos insn_field_cond_field 1414e98e3e1Schristos && r->bit[bit_nr]->field->conditions->type == 1424e98e3e1Schristos insn_field_cond_field) 1434e98e3e1Schristos /* somewhat arbitrary */ 1444e98e3e1Schristos { 1454e98e3e1Schristos int cmp = strcmp (l->bit[bit_nr]->field->conditions->string, 1464e98e3e1Schristos r->bit[bit_nr]->field->conditions-> 1474e98e3e1Schristos string); 1484e98e3e1Schristos if (cmp != 0) 1494e98e3e1Schristos return cmp; 1504e98e3e1Schristos else 1514e98e3e1Schristos continue; 1524e98e3e1Schristos } 1534e98e3e1Schristos if (l->bit[bit_nr]->field->conditions->type == 1544e98e3e1Schristos insn_field_cond_field) 1554e98e3e1Schristos return +1; 1564e98e3e1Schristos if (r->bit[bit_nr]->field->conditions->type == 1574e98e3e1Schristos insn_field_cond_field) 1584e98e3e1Schristos return -1; 1594e98e3e1Schristos /* The case of both fields having constant values should have 1604e98e3e1Schristos already have been handled because such fields are converted 161a2e2270fSchristos into normal constant fields, but we must not make this 162a2e2270fSchristos an assert, as we wouldn't gracefully handle an (invalid) 163a2e2270fSchristos duplicate insn description. */ 1644e98e3e1Schristos continue; 1654e98e3e1Schristos } 1664e98e3e1Schristos if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq) 1674e98e3e1Schristos return +1; /* left = only */ 1684e98e3e1Schristos if (r->bit[bit_nr]->field->conditions->test == insn_field_cond_eq) 1694e98e3e1Schristos return -1; /* right = only */ 1704e98e3e1Schristos /* FIXME: Need to some what arbitrarily order conditional lists */ 1714e98e3e1Schristos continue; 1724e98e3e1Schristos } 1734e98e3e1Schristos l = l->next; 1744e98e3e1Schristos r = r->next; 1754e98e3e1Schristos } 1764e98e3e1Schristos } 1774e98e3e1Schristos 1784e98e3e1Schristos /* same as strcmp */ 1794e98e3e1Schristos static int 1804b169a6bSchristos insn_word_cmp (const insn_word_entry *l, const insn_word_entry *r) 1814e98e3e1Schristos { 1824e98e3e1Schristos while (1) 1834e98e3e1Schristos { 1844e98e3e1Schristos int bit_nr; 1854e98e3e1Schristos if (l == NULL && r == NULL) 1864e98e3e1Schristos return 0; /* all previous fields the same */ 1874e98e3e1Schristos if (l == NULL) 1884e98e3e1Schristos return -1; /* left shorter than right */ 1894e98e3e1Schristos if (r == NULL) 1904e98e3e1Schristos return +1; /* left longer than right */ 1914e98e3e1Schristos for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++) 1924e98e3e1Schristos { 1934e98e3e1Schristos if (l->bit[bit_nr]->mask < r->bit[bit_nr]->mask) 1944e98e3e1Schristos return -1; 1954e98e3e1Schristos if (l->bit[bit_nr]->mask > r->bit[bit_nr]->mask) 1964e98e3e1Schristos return 1; 1974e98e3e1Schristos if (l->bit[bit_nr]->value < r->bit[bit_nr]->value) 1984e98e3e1Schristos return -1; 1994e98e3e1Schristos if (l->bit[bit_nr]->value > r->bit[bit_nr]->value) 2004e98e3e1Schristos return 1; 2014e98e3e1Schristos } 2024e98e3e1Schristos l = l->next; 2034e98e3e1Schristos r = r->next; 2044e98e3e1Schristos } 2054e98e3e1Schristos } 2064e98e3e1Schristos 2074e98e3e1Schristos /* same as strcmp */ 2084e98e3e1Schristos static int 2094b169a6bSchristos opcode_bit_cmp (const opcode_bits *l, const opcode_bits *r) 2104e98e3e1Schristos { 2114e98e3e1Schristos if (l == NULL && r == NULL) 2124e98e3e1Schristos return 0; /* all previous bits the same */ 2134e98e3e1Schristos if (l == NULL) 2144e98e3e1Schristos return -1; /* left shorter than right */ 2154e98e3e1Schristos if (r == NULL) 2164e98e3e1Schristos return +1; /* left longer than right */ 2174e98e3e1Schristos /* most significant word */ 2184e98e3e1Schristos if (l->field->word_nr < r->field->word_nr) 2194e98e3e1Schristos return +1; /* left has more significant word */ 2204e98e3e1Schristos if (l->field->word_nr > r->field->word_nr) 2214e98e3e1Schristos return -1; /* right has more significant word */ 2224e98e3e1Schristos /* most significant bit? */ 2234e98e3e1Schristos if (l->first < r->first) 2244e98e3e1Schristos return +1; /* left as more significant bit */ 2254e98e3e1Schristos if (l->first > r->first) 2264e98e3e1Schristos return -1; /* right as more significant bit */ 2274e98e3e1Schristos /* nr bits? */ 2284e98e3e1Schristos if (l->last < r->last) 2294e98e3e1Schristos return +1; /* left as less bits */ 2304e98e3e1Schristos if (l->last > r->last) 2314e98e3e1Schristos return -1; /* right as less bits */ 2324e98e3e1Schristos /* value? */ 2334e98e3e1Schristos if (l->value < r->value) 2344e98e3e1Schristos return -1; 2354e98e3e1Schristos if (l->value > r->value) 2364e98e3e1Schristos return 1; 2374e98e3e1Schristos return 0; 2384e98e3e1Schristos } 2394e98e3e1Schristos 2404e98e3e1Schristos 2414e98e3e1Schristos /* same as strcmp */ 2424e98e3e1Schristos static int 2434b169a6bSchristos opcode_bits_cmp (const opcode_bits *l, const opcode_bits *r) 2444e98e3e1Schristos { 2454e98e3e1Schristos while (1) 2464e98e3e1Schristos { 2474e98e3e1Schristos int cmp; 2484e98e3e1Schristos if (l == NULL && r == NULL) 2494e98e3e1Schristos return 0; /* all previous bits the same */ 2504e98e3e1Schristos cmp = opcode_bit_cmp (l, r); 2514e98e3e1Schristos if (cmp != 0) 2524e98e3e1Schristos return cmp; 2534e98e3e1Schristos l = l->next; 2544e98e3e1Schristos r = r->next; 2554e98e3e1Schristos } 2564e98e3e1Schristos } 2574e98e3e1Schristos 2584e98e3e1Schristos /* same as strcmp */ 2594e98e3e1Schristos static opcode_bits * 2604e98e3e1Schristos new_opcode_bits (opcode_bits *old_bits, 2614e98e3e1Schristos int value, 2624e98e3e1Schristos int first, 2634e98e3e1Schristos int last, insn_field_entry *field, opcode_field *opcode) 2644e98e3e1Schristos { 2654e98e3e1Schristos opcode_bits *new_bits = ZALLOC (opcode_bits); 2664e98e3e1Schristos new_bits->field = field; 2674e98e3e1Schristos new_bits->value = value; 2684e98e3e1Schristos new_bits->first = first; 2694e98e3e1Schristos new_bits->last = last; 2704e98e3e1Schristos new_bits->opcode = opcode; 2714e98e3e1Schristos 2724e98e3e1Schristos if (old_bits != NULL) 2734e98e3e1Schristos { 2744e98e3e1Schristos opcode_bits *new_list; 2754e98e3e1Schristos opcode_bits **last = &new_list; 2764e98e3e1Schristos new_list = new_opcode_bits (old_bits->next, 2774e98e3e1Schristos old_bits->value, 2784e98e3e1Schristos old_bits->first, 2794e98e3e1Schristos old_bits->last, 2804e98e3e1Schristos old_bits->field, old_bits->opcode); 2814e98e3e1Schristos while (*last != NULL) 2824e98e3e1Schristos { 2834e98e3e1Schristos int cmp = opcode_bit_cmp (new_bits, *last); 2844e98e3e1Schristos if (cmp < 0) /* new < new_list */ 2854e98e3e1Schristos { 2864e98e3e1Schristos break; 2874e98e3e1Schristos } 2884e98e3e1Schristos if (cmp == 0) 2894e98e3e1Schristos { 2904e98e3e1Schristos ERROR ("Duplicated insn bits in list"); 2914e98e3e1Schristos } 2924e98e3e1Schristos last = &(*last)->next; 2934e98e3e1Schristos } 2944e98e3e1Schristos new_bits->next = *last; 2954e98e3e1Schristos *last = new_bits; 2964e98e3e1Schristos return new_list; 2974e98e3e1Schristos } 2984e98e3e1Schristos else 2994e98e3e1Schristos { 3004e98e3e1Schristos return new_bits; 3014e98e3e1Schristos } 3024e98e3e1Schristos } 3034e98e3e1Schristos 3044e98e3e1Schristos /* Same as strcmp(). */ 3054e98e3e1Schristos static int 3064e98e3e1Schristos name_cmp (const char *l, const char *r) 3074e98e3e1Schristos { 3084e98e3e1Schristos if (l == NULL && r == NULL) 3094e98e3e1Schristos return 0; 3104e98e3e1Schristos if (l != NULL && r == NULL) 3114e98e3e1Schristos return -1; 3124e98e3e1Schristos if (l == NULL && r != NULL) 3134e98e3e1Schristos return +1; 3144e98e3e1Schristos return strcmp (l, r); 3154e98e3e1Schristos } 3164e98e3e1Schristos 3174e98e3e1Schristos 3184e98e3e1Schristos typedef enum 3194e98e3e1Schristos { 3204e98e3e1Schristos merge_duplicate_insns, 3214e98e3e1Schristos report_duplicate_insns, 3224e98e3e1Schristos } 3234e98e3e1Schristos duplicate_insn_actions; 3244e98e3e1Schristos 3254e98e3e1Schristos static insn_list * 3264e98e3e1Schristos insn_list_insert (insn_list **cur_insn_ptr, 3274e98e3e1Schristos int *nr_insns, 3284e98e3e1Schristos insn_entry * insn, 3294e98e3e1Schristos opcode_bits *expanded_bits, 3304e98e3e1Schristos opcode_field *opcodes, 3314e98e3e1Schristos int nr_prefetched_words, 3324e98e3e1Schristos duplicate_insn_actions duplicate_action) 3334e98e3e1Schristos { 3344e98e3e1Schristos /* insert it according to the order of the fields & bits */ 3354e98e3e1Schristos for (; (*cur_insn_ptr) != NULL; cur_insn_ptr = &(*cur_insn_ptr)->next) 3364e98e3e1Schristos { 3374e98e3e1Schristos int cmp; 3384e98e3e1Schristos 3394e98e3e1Schristos /* key#1 sort according to the constant fields of each instruction */ 3404e98e3e1Schristos cmp = insn_word_cmp (insn->words, (*cur_insn_ptr)->insn->words); 3414e98e3e1Schristos if (cmp < 0) 3424e98e3e1Schristos break; 3434e98e3e1Schristos else if (cmp > 0) 3444e98e3e1Schristos continue; 3454e98e3e1Schristos 3464e98e3e1Schristos /* key#2 sort according to the expanded bits of each instruction */ 3474e98e3e1Schristos cmp = opcode_bits_cmp (expanded_bits, (*cur_insn_ptr)->expanded_bits); 3484e98e3e1Schristos if (cmp < 0) 3494e98e3e1Schristos break; 3504e98e3e1Schristos else if (cmp > 0) 3514e98e3e1Schristos continue; 3524e98e3e1Schristos 3534e98e3e1Schristos /* key#3 sort according to the non-constant fields of each instruction */ 3544e98e3e1Schristos cmp = insn_field_cmp (insn->words, (*cur_insn_ptr)->insn->words); 3554e98e3e1Schristos if (cmp < 0) 3564e98e3e1Schristos break; 3574e98e3e1Schristos else if (cmp > 0) 3584e98e3e1Schristos continue; 3594e98e3e1Schristos 3604e98e3e1Schristos if (duplicate_action == merge_duplicate_insns) 3614e98e3e1Schristos { 3624e98e3e1Schristos /* key#4: If we're going to merge duplicates, also sort 3634e98e3e1Schristos according to the format_name. Two instructions with 3644e98e3e1Schristos identical decode patterns, but different names, are 3654e98e3e1Schristos considered different when merging. Duplicates are only 3664e98e3e1Schristos important when creating a decode table (implied by 3674e98e3e1Schristos report_duplicate_insns) as such a table only has the 3684e98e3e1Schristos instruction's bit code as a way of differentiating 3694e98e3e1Schristos between instructions. */ 3704e98e3e1Schristos int cmp = name_cmp (insn->format_name, 3714e98e3e1Schristos (*cur_insn_ptr)->insn->format_name); 3724e98e3e1Schristos if (cmp < 0) 3734e98e3e1Schristos break; 3744e98e3e1Schristos else if (cmp > 0) 3754e98e3e1Schristos continue; 3764e98e3e1Schristos } 3774e98e3e1Schristos 3784e98e3e1Schristos if (duplicate_action == merge_duplicate_insns) 3794e98e3e1Schristos { 3804e98e3e1Schristos /* key#5: If we're going to merge duplicates, also sort 3814e98e3e1Schristos according to the name. See comment above for 3824e98e3e1Schristos format_name. */ 3834e98e3e1Schristos int cmp = name_cmp (insn->name, (*cur_insn_ptr)->insn->name); 3844e98e3e1Schristos if (cmp < 0) 3854e98e3e1Schristos break; 3864e98e3e1Schristos else if (cmp > 0) 3874e98e3e1Schristos continue; 3884e98e3e1Schristos } 3894e98e3e1Schristos 3904e98e3e1Schristos /* duplicate keys, report problem */ 3914e98e3e1Schristos switch (duplicate_action) 3924e98e3e1Schristos { 3934e98e3e1Schristos case report_duplicate_insns: 3944e98e3e1Schristos /* It would appear that we have two instructions with the 3954e98e3e1Schristos same constant field values across all words and bits. 3964e98e3e1Schristos This error can also occure when insn_field_cmp() is 3974e98e3e1Schristos failing to differentiate between two instructions that 3984e98e3e1Schristos differ only in their conditional fields. */ 3994e98e3e1Schristos warning (insn->line, 4004e98e3e1Schristos "Two instructions with identical constant fields\n"); 4014e98e3e1Schristos error ((*cur_insn_ptr)->insn->line, 4024e98e3e1Schristos "Location of duplicate instruction\n"); 4034e98e3e1Schristos case merge_duplicate_insns: 4044e98e3e1Schristos /* Add the opcode path to the instructions list */ 4054e98e3e1Schristos if (options.trace.insn_insertion) 4064e98e3e1Schristos { 4074e98e3e1Schristos notify ((*cur_insn_ptr)->insn->line, 4084e98e3e1Schristos "%s.%s: insert merge %s.%s\n", 4094e98e3e1Schristos (*cur_insn_ptr)->insn->format_name, 4104e98e3e1Schristos (*cur_insn_ptr)->insn->name, 4114e98e3e1Schristos insn->format_name, 4124e98e3e1Schristos insn->name); 4134e98e3e1Schristos } 4144e98e3e1Schristos if (opcodes != NULL) 4154e98e3e1Schristos { 4164e98e3e1Schristos insn_opcodes **last = &(*cur_insn_ptr)->opcodes; 4174e98e3e1Schristos while (*last != NULL) 4184e98e3e1Schristos { 4194e98e3e1Schristos last = &(*last)->next; 4204e98e3e1Schristos } 4214e98e3e1Schristos (*last) = ZALLOC (insn_opcodes); 4224e98e3e1Schristos (*last)->opcode = opcodes; 4234e98e3e1Schristos } 4244e98e3e1Schristos /* Use the larger nr_prefetched_words */ 4254e98e3e1Schristos if ((*cur_insn_ptr)->nr_prefetched_words < nr_prefetched_words) 4264e98e3e1Schristos (*cur_insn_ptr)->nr_prefetched_words = nr_prefetched_words; 4274e98e3e1Schristos return (*cur_insn_ptr); 4284e98e3e1Schristos } 4294e98e3e1Schristos 4304e98e3e1Schristos } 4314e98e3e1Schristos 4324e98e3e1Schristos /* create a new list entry and insert it */ 4334e98e3e1Schristos { 4344e98e3e1Schristos insn_list *new_insn = ZALLOC (insn_list); 4354e98e3e1Schristos if (options.trace.insn_insertion) 4364e98e3e1Schristos { 4374e98e3e1Schristos notify (insn->line, 4384e98e3e1Schristos "%s.%s: insert new\n", 4394e98e3e1Schristos insn->format_name, 4404e98e3e1Schristos insn->name); 4414e98e3e1Schristos } 4424e98e3e1Schristos new_insn->insn = insn; 4434e98e3e1Schristos new_insn->expanded_bits = expanded_bits; 4444e98e3e1Schristos new_insn->next = (*cur_insn_ptr); 4454e98e3e1Schristos new_insn->nr_prefetched_words = nr_prefetched_words; 4464e98e3e1Schristos if (opcodes != NULL) 4474e98e3e1Schristos { 4484e98e3e1Schristos new_insn->opcodes = ZALLOC (insn_opcodes); 4494e98e3e1Schristos new_insn->opcodes->opcode = opcodes; 4504e98e3e1Schristos } 4514e98e3e1Schristos (*cur_insn_ptr) = new_insn; 4524e98e3e1Schristos } 4534e98e3e1Schristos 4544e98e3e1Schristos *nr_insns += 1; 4554e98e3e1Schristos 4564e98e3e1Schristos return (*cur_insn_ptr); 4574e98e3e1Schristos } 4584e98e3e1Schristos 4594e98e3e1Schristos 4604e98e3e1Schristos extern void 4614e98e3e1Schristos gen_entry_traverse_tree (lf *file, 4624b169a6bSchristos const gen_entry *table, 4634e98e3e1Schristos int depth, 4644e98e3e1Schristos gen_entry_handler * start, 4654e98e3e1Schristos gen_entry_handler * leaf, 4664e98e3e1Schristos gen_entry_handler * end, void *data) 4674e98e3e1Schristos { 4684e98e3e1Schristos gen_entry *entry; 4694e98e3e1Schristos 4704e98e3e1Schristos ASSERT (table !=NULL); 4714e98e3e1Schristos ASSERT (table->opcode != NULL); 4724e98e3e1Schristos ASSERT (table->nr_entries > 0); 4734e98e3e1Schristos ASSERT (table->entries != 0); 4744e98e3e1Schristos 4754e98e3e1Schristos /* prefix */ 4764e98e3e1Schristos if (start != NULL && depth >= 0) 4774e98e3e1Schristos { 4784e98e3e1Schristos start (file, table, depth, data); 4794e98e3e1Schristos } 4804e98e3e1Schristos /* infix leaves */ 4814e98e3e1Schristos for (entry = table->entries; entry != NULL; entry = entry->sibling) 4824e98e3e1Schristos { 4834e98e3e1Schristos if (entry->entries != NULL && depth != 0) 4844e98e3e1Schristos { 4854e98e3e1Schristos gen_entry_traverse_tree (file, entry, depth + 1, 4864e98e3e1Schristos start, leaf, end, data); 4874e98e3e1Schristos } 4884e98e3e1Schristos else if (depth >= 0) 4894e98e3e1Schristos { 4904e98e3e1Schristos if (leaf != NULL) 4914e98e3e1Schristos { 4924e98e3e1Schristos leaf (file, entry, depth, data); 4934e98e3e1Schristos } 4944e98e3e1Schristos } 4954e98e3e1Schristos } 4964e98e3e1Schristos /* postfix */ 4974e98e3e1Schristos if (end != NULL && depth >= 0) 4984e98e3e1Schristos { 4994e98e3e1Schristos end (file, table, depth, data); 5004e98e3e1Schristos } 5014e98e3e1Schristos } 5024e98e3e1Schristos 5034e98e3e1Schristos 5044e98e3e1Schristos 5054e98e3e1Schristos /* create a list element containing a single gen_table entry */ 5064e98e3e1Schristos 5074e98e3e1Schristos static gen_list * 5084b169a6bSchristos make_table (const insn_table *isa, 5094b169a6bSchristos const decode_table *rules, 5104b169a6bSchristos const model_entry *model) 5114e98e3e1Schristos { 5124e98e3e1Schristos insn_entry *insn; 5134e98e3e1Schristos gen_list *entry = ZALLOC (gen_list); 5144e98e3e1Schristos entry->table = ZALLOC (gen_entry); 5154e98e3e1Schristos entry->table->top = entry; 5164e98e3e1Schristos entry->model = model; 5174e98e3e1Schristos entry->isa = isa; 5184e98e3e1Schristos for (insn = isa->insns; insn != NULL; insn = insn->next) 5194e98e3e1Schristos { 5204e98e3e1Schristos if (model == NULL 5214e98e3e1Schristos || insn->processors == NULL 5224e98e3e1Schristos || filter_is_member (insn->processors, model->name)) 5234e98e3e1Schristos { 5244e98e3e1Schristos insn_list_insert (&entry->table->insns, &entry->table->nr_insns, insn, NULL, /* expanded_bits - none yet */ 5254e98e3e1Schristos NULL, /* opcodes - none yet */ 5264e98e3e1Schristos 0, /* nr_prefetched_words - none yet */ 5274e98e3e1Schristos report_duplicate_insns); 5284e98e3e1Schristos } 5294e98e3e1Schristos } 5304e98e3e1Schristos entry->table->opcode_rule = rules; 5314e98e3e1Schristos return entry; 5324e98e3e1Schristos } 5334e98e3e1Schristos 5344e98e3e1Schristos 5354e98e3e1Schristos gen_table * 5364b169a6bSchristos make_gen_tables (const insn_table *isa, const decode_table *rules) 5374e98e3e1Schristos { 5384e98e3e1Schristos gen_table *gen = ZALLOC (gen_table); 5394e98e3e1Schristos gen->isa = isa; 5404e98e3e1Schristos gen->rules = rules; 5414e98e3e1Schristos if (options.gen.multi_sim) 5424e98e3e1Schristos { 5434e98e3e1Schristos gen_list **last = &gen->tables; 5444e98e3e1Schristos model_entry *model; 5454e98e3e1Schristos filter *processors; 5464e98e3e1Schristos if (options.model_filter != NULL) 5474e98e3e1Schristos processors = options.model_filter; 5484e98e3e1Schristos else 5494e98e3e1Schristos processors = isa->model->processors; 5504e98e3e1Schristos for (model = isa->model->models; model != NULL; model = model->next) 5514e98e3e1Schristos { 5524e98e3e1Schristos if (filter_is_member (processors, model->name)) 5534e98e3e1Schristos { 5544e98e3e1Schristos *last = make_table (isa, rules, model); 5554e98e3e1Schristos last = &(*last)->next; 5564e98e3e1Schristos } 5574e98e3e1Schristos } 5584e98e3e1Schristos } 5594e98e3e1Schristos else 5604e98e3e1Schristos { 5614e98e3e1Schristos gen->tables = make_table (isa, rules, NULL); 5624e98e3e1Schristos } 5634e98e3e1Schristos return gen; 5644e98e3e1Schristos } 5654e98e3e1Schristos 5664e98e3e1Schristos 5674e98e3e1Schristos /****************************************************************/ 5684e98e3e1Schristos 5694e98e3e1Schristos /* Is the bit, according to the decode rule, identical across all the 5704e98e3e1Schristos instructions? */ 5714e98e3e1Schristos static int 5724b169a6bSchristos insns_bit_useless (const insn_list *insns, const decode_table *rule, int bit_nr) 5734e98e3e1Schristos { 5744b169a6bSchristos const insn_list *entry; 5754e98e3e1Schristos int value = -1; 5764e98e3e1Schristos int is_useless = 1; /* cleared if something actually found */ 5774e98e3e1Schristos 5784e98e3e1Schristos /* check the instructions for some constant value in at least one of 5794e98e3e1Schristos the bit fields */ 5804e98e3e1Schristos for (entry = insns; entry != NULL; entry = entry->next) 5814e98e3e1Schristos { 5824e98e3e1Schristos insn_word_entry *word = entry->insn->word[rule->word_nr]; 5834e98e3e1Schristos insn_bit_entry *bit = word->bit[bit_nr]; 5844e98e3e1Schristos switch (bit->field->type) 5854e98e3e1Schristos { 5864e98e3e1Schristos case insn_field_invalid: 5874e98e3e1Schristos ASSERT (0); 5884e98e3e1Schristos break; 5894e98e3e1Schristos case insn_field_wild: 5904e98e3e1Schristos case insn_field_reserved: 5914e98e3e1Schristos /* neither useless or useful - ignore */ 5924e98e3e1Schristos break; 5934e98e3e1Schristos case insn_field_int: 5944e98e3e1Schristos switch (rule->search) 5954e98e3e1Schristos { 5964e98e3e1Schristos case decode_find_strings: 5974e98e3e1Schristos /* an integer isn't a string */ 5984e98e3e1Schristos return 1; 5994e98e3e1Schristos case decode_find_constants: 6004e98e3e1Schristos case decode_find_mixed: 6014e98e3e1Schristos /* an integer is useful if its value isn't the same 6024e98e3e1Schristos between all instructions. The first time through the 6034e98e3e1Schristos value is saved, the second time through (if the 6044e98e3e1Schristos values differ) it is marked as useful. */ 6054e98e3e1Schristos if (value < 0) 6064e98e3e1Schristos value = bit->value; 6074e98e3e1Schristos else if (value != bit->value) 6084e98e3e1Schristos is_useless = 0; 6094e98e3e1Schristos break; 6104e98e3e1Schristos } 6114e98e3e1Schristos break; 6124e98e3e1Schristos case insn_field_string: 6134e98e3e1Schristos switch (rule->search) 6144e98e3e1Schristos { 6154e98e3e1Schristos case decode_find_strings: 6164e98e3e1Schristos /* at least one string, keep checking */ 6174e98e3e1Schristos is_useless = 0; 6184e98e3e1Schristos break; 6194e98e3e1Schristos case decode_find_constants: 6204e98e3e1Schristos case decode_find_mixed: 6214e98e3e1Schristos if (filter_is_member (rule->constant_field_names, 6224e98e3e1Schristos bit->field->val_string)) 6234e98e3e1Schristos /* a string field forced to constant? */ 6244e98e3e1Schristos is_useless = 0; 625a2e2270fSchristos else if (bit->field->conditions != NULL 626a2e2270fSchristos && bit->field->conditions->test == insn_field_cond_eq 627a2e2270fSchristos && bit->field->conditions->type == insn_field_cond_value) 628a2e2270fSchristos { 629a2e2270fSchristos int shift = bit->field->last - bit_nr; 630a2e2270fSchristos int bitvalue = (bit->field->conditions->value >> shift) & 1; 631a2e2270fSchristos 632a2e2270fSchristos if (value < 0) 633a2e2270fSchristos value = bitvalue; 634a2e2270fSchristos else if (value != bitvalue) 635a2e2270fSchristos is_useless = 0; 636a2e2270fSchristos } 6374e98e3e1Schristos else if (rule->search == decode_find_constants) 6384e98e3e1Schristos /* the string field isn't constant */ 6394e98e3e1Schristos return 1; 6404e98e3e1Schristos break; 6414e98e3e1Schristos } 6424e98e3e1Schristos } 6434e98e3e1Schristos } 6444e98e3e1Schristos 6454e98e3e1Schristos /* Given only one constant value has been found, check through all 6464e98e3e1Schristos the instructions to see if at least one conditional makes it 6474e98e3e1Schristos usefull */ 6484e98e3e1Schristos if (value >= 0 && is_useless) 6494e98e3e1Schristos { 6504e98e3e1Schristos for (entry = insns; entry != NULL; entry = entry->next) 6514e98e3e1Schristos { 6524e98e3e1Schristos insn_word_entry *word = entry->insn->word[rule->word_nr]; 6534e98e3e1Schristos insn_bit_entry *bit = word->bit[bit_nr]; 6544e98e3e1Schristos switch (bit->field->type) 6554e98e3e1Schristos { 6564e98e3e1Schristos case insn_field_invalid: 6574e98e3e1Schristos ASSERT (0); 6584e98e3e1Schristos break; 6594e98e3e1Schristos case insn_field_wild: 6604e98e3e1Schristos case insn_field_reserved: 6614e98e3e1Schristos case insn_field_int: 6624e98e3e1Schristos /* already processed */ 6634e98e3e1Schristos break; 6644e98e3e1Schristos case insn_field_string: 6654e98e3e1Schristos switch (rule->search) 6664e98e3e1Schristos { 6674e98e3e1Schristos case decode_find_strings: 6684e98e3e1Schristos case decode_find_constants: 6694e98e3e1Schristos /* already processed */ 6704e98e3e1Schristos break; 6714e98e3e1Schristos case decode_find_mixed: 6724e98e3e1Schristos /* string field with conditions. If this condition 6734e98e3e1Schristos eliminates the value then the compare is useful */ 6744e98e3e1Schristos if (bit->field->conditions != NULL) 6754e98e3e1Schristos { 6764e98e3e1Schristos insn_field_cond *condition; 6774e98e3e1Schristos int shift = bit->field->last - bit_nr; 6784e98e3e1Schristos for (condition = bit->field->conditions; 6794e98e3e1Schristos condition != NULL; condition = condition->next) 6804e98e3e1Schristos { 6814e98e3e1Schristos switch (condition->type) 6824e98e3e1Schristos { 6834e98e3e1Schristos case insn_field_cond_value: 6844e98e3e1Schristos switch (condition->test) 6854e98e3e1Schristos { 6864e98e3e1Schristos case insn_field_cond_ne: 6874e98e3e1Schristos if (((condition->value >> shift) & 1) 6884e98e3e1Schristos == (unsigned) value) 6894e98e3e1Schristos /* conditional field excludes the 6904e98e3e1Schristos current value */ 6914e98e3e1Schristos is_useless = 0; 6924e98e3e1Schristos break; 6934e98e3e1Schristos case insn_field_cond_eq: 6944e98e3e1Schristos if (((condition->value >> shift) & 1) 6954e98e3e1Schristos != (unsigned) value) 6964e98e3e1Schristos /* conditional field requires the 6974e98e3e1Schristos current value */ 6984e98e3e1Schristos is_useless = 0; 6994e98e3e1Schristos break; 7004e98e3e1Schristos } 7014e98e3e1Schristos break; 7024e98e3e1Schristos case insn_field_cond_field: 7034e98e3e1Schristos /* are these handled separatly? */ 7044e98e3e1Schristos break; 7054e98e3e1Schristos } 7064e98e3e1Schristos } 7074e98e3e1Schristos } 7084e98e3e1Schristos } 7094e98e3e1Schristos } 7104e98e3e1Schristos } 7114e98e3e1Schristos } 7124e98e3e1Schristos 7134e98e3e1Schristos return is_useless; 7144e98e3e1Schristos } 7154e98e3e1Schristos 7164e98e3e1Schristos 7174e98e3e1Schristos /* go through a gen-table's list of instruction formats looking for a 7184e98e3e1Schristos range of bits that meet the decode table RULEs requirements */ 7194e98e3e1Schristos 7204e98e3e1Schristos static opcode_field * 7214e98e3e1Schristos gen_entry_find_opcode_field (insn_list *insns, 7224b169a6bSchristos const decode_table *rule, int string_only) 7234e98e3e1Schristos { 7244e98e3e1Schristos opcode_field curr_opcode; 7254e98e3e1Schristos ASSERT (rule != NULL); 7264e98e3e1Schristos 7274e98e3e1Schristos memset (&curr_opcode, 0, sizeof (curr_opcode)); 7284e98e3e1Schristos curr_opcode.word_nr = rule->word_nr; 7294e98e3e1Schristos curr_opcode.first = rule->first; 7304e98e3e1Schristos curr_opcode.last = rule->last; 7314e98e3e1Schristos 7324e98e3e1Schristos /* Try to reduce the size of first..last in accordance with the 7334e98e3e1Schristos decode rules */ 7344e98e3e1Schristos 7354e98e3e1Schristos while (curr_opcode.first <= rule->last) 7364e98e3e1Schristos { 7374e98e3e1Schristos if (insns_bit_useless (insns, rule, curr_opcode.first)) 7384e98e3e1Schristos curr_opcode.first++; 7394e98e3e1Schristos else 7404e98e3e1Schristos break; 7414e98e3e1Schristos } 7424e98e3e1Schristos while (curr_opcode.last >= rule->first) 7434e98e3e1Schristos { 7444e98e3e1Schristos if (insns_bit_useless (insns, rule, curr_opcode.last)) 7454e98e3e1Schristos curr_opcode.last--; 7464e98e3e1Schristos else 7474e98e3e1Schristos break; 7484e98e3e1Schristos } 7494e98e3e1Schristos 7504e98e3e1Schristos /* did the final opcode field end up being empty? */ 7514e98e3e1Schristos if (curr_opcode.first > curr_opcode.last) 7524e98e3e1Schristos { 7534e98e3e1Schristos return NULL; 7544e98e3e1Schristos } 7554e98e3e1Schristos ASSERT (curr_opcode.last >= rule->first); 7564e98e3e1Schristos ASSERT (curr_opcode.first <= rule->last); 7574e98e3e1Schristos ASSERT (curr_opcode.first <= curr_opcode.last); 7584e98e3e1Schristos 7594e98e3e1Schristos /* Ensure that, for the non string only case, the opcode includes 7604e98e3e1Schristos the range forced_first .. forced_last */ 7614e98e3e1Schristos if (!string_only && curr_opcode.first > rule->force_first) 7624e98e3e1Schristos { 7634e98e3e1Schristos curr_opcode.first = rule->force_first; 7644e98e3e1Schristos } 7654e98e3e1Schristos if (!string_only && curr_opcode.last < rule->force_last) 7664e98e3e1Schristos { 7674e98e3e1Schristos curr_opcode.last = rule->force_last; 7684e98e3e1Schristos } 7694e98e3e1Schristos 7704e98e3e1Schristos /* For the string only case, force just the lower bound (so that the 7714e98e3e1Schristos shift can be eliminated) */ 7724e98e3e1Schristos if (string_only && rule->force_last == options.insn_bit_size - 1) 7734e98e3e1Schristos { 7744e98e3e1Schristos curr_opcode.last = options.insn_bit_size - 1; 7754e98e3e1Schristos } 7764e98e3e1Schristos 7774e98e3e1Schristos /* handle any special cases */ 7784e98e3e1Schristos switch (rule->type) 7794e98e3e1Schristos { 7804e98e3e1Schristos case normal_decode_rule: 7814e98e3e1Schristos /* let the above apply */ 7824e98e3e1Schristos curr_opcode.nr_opcodes = 7834e98e3e1Schristos (1 << (curr_opcode.last - curr_opcode.first + 1)); 7844e98e3e1Schristos break; 7854e98e3e1Schristos case boolean_rule: 7864e98e3e1Schristos curr_opcode.is_boolean = 1; 7874e98e3e1Schristos curr_opcode.boolean_constant = rule->constant; 7884e98e3e1Schristos curr_opcode.nr_opcodes = 2; 7894e98e3e1Schristos break; 7904e98e3e1Schristos } 7914e98e3e1Schristos 7924e98e3e1Schristos { 7934e98e3e1Schristos opcode_field *new_field = ZALLOC (opcode_field); 7944e98e3e1Schristos memcpy (new_field, &curr_opcode, sizeof (opcode_field)); 7954e98e3e1Schristos return new_field; 7964e98e3e1Schristos } 7974e98e3e1Schristos } 7984e98e3e1Schristos 7994e98e3e1Schristos 8004e98e3e1Schristos static void 8014e98e3e1Schristos gen_entry_insert_insn (gen_entry *table, 8024e98e3e1Schristos insn_entry * old_insn, 8034e98e3e1Schristos int new_word_nr, 8044e98e3e1Schristos int new_nr_prefetched_words, 8054e98e3e1Schristos int new_opcode_nr, opcode_bits *new_bits) 8064e98e3e1Schristos { 8074e98e3e1Schristos gen_entry **entry = &table->entries; 8084e98e3e1Schristos 8094e98e3e1Schristos /* find the new table for this entry */ 8104e98e3e1Schristos while ((*entry) != NULL && (*entry)->opcode_nr < new_opcode_nr) 8114e98e3e1Schristos { 8124e98e3e1Schristos entry = &(*entry)->sibling; 8134e98e3e1Schristos } 8144e98e3e1Schristos 8154e98e3e1Schristos if ((*entry) == NULL || (*entry)->opcode_nr != new_opcode_nr) 8164e98e3e1Schristos { 8174e98e3e1Schristos /* insert the missing entry */ 8184e98e3e1Schristos gen_entry *new_entry = ZALLOC (gen_entry); 8194e98e3e1Schristos new_entry->sibling = (*entry); 8204e98e3e1Schristos (*entry) = new_entry; 8214e98e3e1Schristos table->nr_entries++; 8224e98e3e1Schristos /* fill it in */ 8234e98e3e1Schristos new_entry->top = table->top; 8244e98e3e1Schristos new_entry->opcode_nr = new_opcode_nr; 8254e98e3e1Schristos new_entry->word_nr = new_word_nr; 8264e98e3e1Schristos new_entry->expanded_bits = new_bits; 8274e98e3e1Schristos new_entry->opcode_rule = table->opcode_rule->next; 8284e98e3e1Schristos new_entry->parent = table; 8294e98e3e1Schristos new_entry->nr_prefetched_words = new_nr_prefetched_words; 8304e98e3e1Schristos } 8314e98e3e1Schristos /* ASSERT new_bits == cur_entry bits */ 8324e98e3e1Schristos ASSERT ((*entry) != NULL && (*entry)->opcode_nr == new_opcode_nr); 8334e98e3e1Schristos insn_list_insert (&(*entry)->insns, &(*entry)->nr_insns, old_insn, NULL, /* expanded_bits - only in final list */ 8344e98e3e1Schristos NULL, /* opcodes - only in final list */ 8354e98e3e1Schristos new_nr_prefetched_words, /* for this table */ 8364e98e3e1Schristos report_duplicate_insns); 8374e98e3e1Schristos } 8384e98e3e1Schristos 8394e98e3e1Schristos 8404e98e3e1Schristos static void 8414e98e3e1Schristos gen_entry_expand_opcode (gen_entry *table, 8424e98e3e1Schristos insn_entry * instruction, 8434e98e3e1Schristos int bit_nr, int opcode_nr, opcode_bits *bits) 8444e98e3e1Schristos { 8454e98e3e1Schristos if (bit_nr > table->opcode->last) 8464e98e3e1Schristos { 8474e98e3e1Schristos /* Only include the hardwired bit information with an entry IF 8484e98e3e1Schristos that entry (and hence its functions) are being duplicated. */ 8494e98e3e1Schristos if (options.trace.insn_expansion) 8504e98e3e1Schristos { 8514e98e3e1Schristos print_gen_entry_path (table->opcode_rule->line, table, notify); 8524e98e3e1Schristos notify (NULL, ": insert %d - %s.%s%s\n", 8534e98e3e1Schristos opcode_nr, 8544e98e3e1Schristos instruction->format_name, 8554e98e3e1Schristos instruction->name, 8564e98e3e1Schristos (table->opcode_rule-> 8574e98e3e1Schristos with_duplicates ? " (duplicated)" : "")); 8584e98e3e1Schristos } 8594e98e3e1Schristos if (table->opcode_rule->with_duplicates) 8604e98e3e1Schristos { 8614e98e3e1Schristos gen_entry_insert_insn (table, instruction, 8624e98e3e1Schristos table->opcode->word_nr, 8634e98e3e1Schristos table->nr_prefetched_words, opcode_nr, bits); 8644e98e3e1Schristos } 8654e98e3e1Schristos else 8664e98e3e1Schristos { 8674e98e3e1Schristos gen_entry_insert_insn (table, instruction, 8684e98e3e1Schristos table->opcode->word_nr, 8694e98e3e1Schristos table->nr_prefetched_words, opcode_nr, NULL); 8704e98e3e1Schristos } 8714e98e3e1Schristos } 8724e98e3e1Schristos else 8734e98e3e1Schristos { 8744e98e3e1Schristos insn_word_entry *word = instruction->word[table->opcode->word_nr]; 8754e98e3e1Schristos insn_field_entry *field = word->bit[bit_nr]->field; 8764e98e3e1Schristos int last_pos = ((field->last < table->opcode->last) 8774e98e3e1Schristos ? field->last : table->opcode->last); 8784e98e3e1Schristos int first_pos = ((field->first > table->opcode->first) 8794e98e3e1Schristos ? field->first : table->opcode->first); 8804e98e3e1Schristos int width = last_pos - first_pos + 1; 8814e98e3e1Schristos switch (field->type) 8824e98e3e1Schristos { 8834e98e3e1Schristos case insn_field_int: 8844e98e3e1Schristos { 8854e98e3e1Schristos int val; 8864e98e3e1Schristos val = sub_val (field->val_int, field->last, first_pos, last_pos); 8874e98e3e1Schristos gen_entry_expand_opcode (table, instruction, 8884e98e3e1Schristos last_pos + 1, 8894e98e3e1Schristos ((opcode_nr << width) | val), bits); 8904e98e3e1Schristos break; 8914e98e3e1Schristos } 8924e98e3e1Schristos default: 8934e98e3e1Schristos { 8944e98e3e1Schristos if (field->type == insn_field_reserved) 8954e98e3e1Schristos gen_entry_expand_opcode (table, instruction, 8964e98e3e1Schristos last_pos + 1, 8974e98e3e1Schristos ((opcode_nr << width)), bits); 8984e98e3e1Schristos else 8994e98e3e1Schristos { 9004e98e3e1Schristos int val; 9014e98e3e1Schristos int last_val = (table->opcode->is_boolean ? 2 : (1 << width)); 9024e98e3e1Schristos for (val = 0; val < last_val; val++) 9034e98e3e1Schristos { 9044e98e3e1Schristos /* check to see if the value has been precluded 9054e98e3e1Schristos (by a conditional) in some way */ 9064e98e3e1Schristos int is_precluded; 9074e98e3e1Schristos insn_field_cond *condition; 9084e98e3e1Schristos for (condition = field->conditions, is_precluded = 0; 9094e98e3e1Schristos condition != NULL && !is_precluded; 9104e98e3e1Schristos condition = condition->next) 9114e98e3e1Schristos { 9124e98e3e1Schristos switch (condition->type) 9134e98e3e1Schristos { 9144e98e3e1Schristos case insn_field_cond_value: 9154e98e3e1Schristos { 9164e98e3e1Schristos int value = 9174e98e3e1Schristos sub_val (condition->value, field->last, 9184e98e3e1Schristos first_pos, last_pos); 9194e98e3e1Schristos switch (condition->test) 9204e98e3e1Schristos { 9214e98e3e1Schristos case insn_field_cond_ne: 9224e98e3e1Schristos if (value == val) 9234e98e3e1Schristos is_precluded = 1; 9244e98e3e1Schristos break; 9254e98e3e1Schristos case insn_field_cond_eq: 9264e98e3e1Schristos if (value != val) 9274e98e3e1Schristos is_precluded = 1; 9284e98e3e1Schristos break; 9294e98e3e1Schristos } 9304e98e3e1Schristos break; 9314e98e3e1Schristos } 9324e98e3e1Schristos case insn_field_cond_field: 9334e98e3e1Schristos { 9344e98e3e1Schristos int value = -1; 9354e98e3e1Schristos opcode_bits *bit; 9364e98e3e1Schristos gen_entry *t = NULL; 9374e98e3e1Schristos /* Try to find a value for the 9384e98e3e1Schristos conditional by looking back through 9394e98e3e1Schristos the previously defined bits for one 9404e98e3e1Schristos that covers the designated 9414e98e3e1Schristos conditional field */ 9424e98e3e1Schristos for (bit = bits; bit != NULL; bit = bit->next) 9434e98e3e1Schristos { 9444e98e3e1Schristos if (bit->field->word_nr == 9454e98e3e1Schristos condition->field->word_nr 9464e98e3e1Schristos && bit->first <= condition->field->first 9474e98e3e1Schristos && bit->last >= condition->field->last) 9484e98e3e1Schristos { 9494e98e3e1Schristos /* the bit field fully specified 9504e98e3e1Schristos the conditional field's value */ 9514e98e3e1Schristos value = sub_val (bit->value, bit->last, 9524e98e3e1Schristos condition->field-> 9534e98e3e1Schristos first, 9544e98e3e1Schristos condition->field-> 9554e98e3e1Schristos last); 9564e98e3e1Schristos } 9574e98e3e1Schristos } 9584e98e3e1Schristos /* Try to find a value by looking 9594e98e3e1Schristos through this and previous tables */ 9604e98e3e1Schristos if (bit == NULL) 9614e98e3e1Schristos { 9624e98e3e1Schristos for (t = table; 9634e98e3e1Schristos t->parent != NULL; t = t->parent) 9644e98e3e1Schristos { 9654e98e3e1Schristos if (t->parent->opcode->word_nr == 9664e98e3e1Schristos condition->field->word_nr 9674e98e3e1Schristos && t->parent->opcode->first <= 9684e98e3e1Schristos condition->field->first 9694e98e3e1Schristos && t->parent->opcode->last >= 9704e98e3e1Schristos condition->field->last) 9714e98e3e1Schristos { 9724e98e3e1Schristos /* the table entry fully 9734e98e3e1Schristos specified the condition 9744e98e3e1Schristos field's value */ 9754e98e3e1Schristos /* extract the field's value 9764e98e3e1Schristos from the opcode */ 9774e98e3e1Schristos value = 9784e98e3e1Schristos sub_val (t->opcode_nr, 9794e98e3e1Schristos t->parent->opcode->last, 9804e98e3e1Schristos condition->field->first, 9814e98e3e1Schristos condition->field->last); 9824e98e3e1Schristos /* this is a requirement of 9834e98e3e1Schristos a conditonal field 9844e98e3e1Schristos refering to another field */ 9854e98e3e1Schristos ASSERT ((condition->field->first - 9864e98e3e1Schristos condition->field->last) == 9874e98e3e1Schristos (first_pos - last_pos)); 9884e98e3e1Schristos printf 9894e98e3e1Schristos ("value=%d, opcode_nr=%d, last=%d, [%d..%d]\n", 9904e98e3e1Schristos value, t->opcode_nr, 9914e98e3e1Schristos t->parent->opcode->last, 9924e98e3e1Schristos condition->field->first, 9934e98e3e1Schristos condition->field->last); 9944e98e3e1Schristos } 9954e98e3e1Schristos } 9964e98e3e1Schristos } 9974e98e3e1Schristos if (bit == NULL && t == NULL) 9984e98e3e1Schristos error (instruction->line, 9994b169a6bSchristos "Conditional `%s' of field `%s' isn't expanded\n", 10004e98e3e1Schristos condition->string, field->val_string); 10014e98e3e1Schristos switch (condition->test) 10024e98e3e1Schristos { 10034e98e3e1Schristos case insn_field_cond_ne: 10044e98e3e1Schristos if (value == val) 10054e98e3e1Schristos is_precluded = 1; 10064e98e3e1Schristos break; 10074e98e3e1Schristos case insn_field_cond_eq: 10084e98e3e1Schristos if (value != val) 10094e98e3e1Schristos is_precluded = 1; 10104e98e3e1Schristos break; 10114e98e3e1Schristos } 10124e98e3e1Schristos break; 10134e98e3e1Schristos } 10144e98e3e1Schristos } 10154e98e3e1Schristos } 10164e98e3e1Schristos if (!is_precluded) 10174e98e3e1Schristos { 10184e98e3e1Schristos /* Only add additional hardwired bit 10194e98e3e1Schristos information if the entry is not going to 10204e98e3e1Schristos later be combined */ 10214e98e3e1Schristos if (table->opcode_rule->with_combine) 10224e98e3e1Schristos { 10234e98e3e1Schristos gen_entry_expand_opcode (table, instruction, 10244e98e3e1Schristos last_pos + 1, 10254e98e3e1Schristos ((opcode_nr << width) | 10264e98e3e1Schristos val), bits); 10274e98e3e1Schristos } 10284e98e3e1Schristos else 10294e98e3e1Schristos { 10304e98e3e1Schristos opcode_bits *new_bits = 10314e98e3e1Schristos new_opcode_bits (bits, val, 10324e98e3e1Schristos first_pos, last_pos, 10334e98e3e1Schristos field, 10344e98e3e1Schristos table->opcode); 10354e98e3e1Schristos gen_entry_expand_opcode (table, instruction, 10364e98e3e1Schristos last_pos + 1, 10374e98e3e1Schristos ((opcode_nr << width) | 10384e98e3e1Schristos val), new_bits); 10394e98e3e1Schristos } 10404e98e3e1Schristos } 10414e98e3e1Schristos } 10424e98e3e1Schristos } 10434e98e3e1Schristos } 10444e98e3e1Schristos } 10454e98e3e1Schristos } 10464e98e3e1Schristos } 10474e98e3e1Schristos 10484e98e3e1Schristos static void 10494e98e3e1Schristos gen_entry_insert_expanding (gen_entry *table, insn_entry * instruction) 10504e98e3e1Schristos { 10514e98e3e1Schristos gen_entry_expand_opcode (table, 10524e98e3e1Schristos instruction, 10534e98e3e1Schristos table->opcode->first, 0, table->expanded_bits); 10544e98e3e1Schristos } 10554e98e3e1Schristos 10564e98e3e1Schristos 10574e98e3e1Schristos static int 10584e98e3e1Schristos insns_match_format_names (insn_list *insns, filter *format_names) 10594e98e3e1Schristos { 10604e98e3e1Schristos if (format_names != NULL) 10614e98e3e1Schristos { 10624e98e3e1Schristos insn_list *i; 10634e98e3e1Schristos for (i = insns; i != NULL; i = i->next) 10644e98e3e1Schristos { 10654e98e3e1Schristos if (i->insn->format_name != NULL 10664e98e3e1Schristos && !filter_is_member (format_names, i->insn->format_name)) 10674e98e3e1Schristos return 0; 10684e98e3e1Schristos } 10694e98e3e1Schristos } 10704e98e3e1Schristos return 1; 10714e98e3e1Schristos } 10724e98e3e1Schristos 10734e98e3e1Schristos static int 10744e98e3e1Schristos table_matches_path (gen_entry *table, decode_path_list *paths) 10754e98e3e1Schristos { 10764e98e3e1Schristos if (paths == NULL) 10774e98e3e1Schristos return 1; 10784e98e3e1Schristos while (paths != NULL) 10794e98e3e1Schristos { 10804e98e3e1Schristos gen_entry *entry = table; 10814e98e3e1Schristos decode_path *path = paths->path; 10824e98e3e1Schristos while (1) 10834e98e3e1Schristos { 10844e98e3e1Schristos if (entry == NULL && path == NULL) 10854e98e3e1Schristos return 1; 10864e98e3e1Schristos if (entry == NULL || path == NULL) 10874e98e3e1Schristos break; 10884e98e3e1Schristos if (entry->opcode_nr != path->opcode_nr) 10894e98e3e1Schristos break; 10904e98e3e1Schristos entry = entry->parent; 10914e98e3e1Schristos path = path->parent; 10924e98e3e1Schristos } 10934e98e3e1Schristos paths = paths->next; 10944e98e3e1Schristos } 10954e98e3e1Schristos return 0; 10964e98e3e1Schristos } 10974e98e3e1Schristos 10984e98e3e1Schristos 10994e98e3e1Schristos static int 11004e98e3e1Schristos insns_match_conditions (insn_list *insns, decode_cond *conditions) 11014e98e3e1Schristos { 11024e98e3e1Schristos if (conditions != NULL) 11034e98e3e1Schristos { 11044e98e3e1Schristos insn_list *i; 11054e98e3e1Schristos for (i = insns; i != NULL; i = i->next) 11064e98e3e1Schristos { 11074e98e3e1Schristos decode_cond *cond; 11084e98e3e1Schristos for (cond = conditions; cond != NULL; cond = cond->next) 11094e98e3e1Schristos { 11104e98e3e1Schristos int bit_nr; 11114e98e3e1Schristos if (i->insn->nr_words <= cond->word_nr) 11124e98e3e1Schristos return 0; 11134e98e3e1Schristos for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++) 11144e98e3e1Schristos { 11154e98e3e1Schristos if (!cond->mask[bit_nr]) 11164e98e3e1Schristos continue; 11174e98e3e1Schristos if (!i->insn->word[cond->word_nr]->bit[bit_nr]->mask) 11184e98e3e1Schristos return 0; 11194e98e3e1Schristos if ((i->insn->word[cond->word_nr]->bit[bit_nr]->value 11204e98e3e1Schristos == cond->value[bit_nr]) == !cond->is_equal) 11214e98e3e1Schristos return 0; 11224e98e3e1Schristos } 11234e98e3e1Schristos } 11244e98e3e1Schristos } 11254e98e3e1Schristos } 11264e98e3e1Schristos return 1; 11274e98e3e1Schristos } 11284e98e3e1Schristos 11294e98e3e1Schristos static int 11304b169a6bSchristos insns_match_nr_words (const insn_list *insns, int nr_words) 11314e98e3e1Schristos { 11324b169a6bSchristos const insn_list *i; 11334e98e3e1Schristos for (i = insns; i != NULL; i = i->next) 11344e98e3e1Schristos { 11354e98e3e1Schristos if (i->insn->nr_words < nr_words) 11364e98e3e1Schristos return 0; 11374e98e3e1Schristos } 11384e98e3e1Schristos return 1; 11394e98e3e1Schristos } 11404e98e3e1Schristos 11414e98e3e1Schristos static int 11424b169a6bSchristos insn_list_cmp (const insn_list *l, const insn_list *r) 11434e98e3e1Schristos { 11444e98e3e1Schristos while (1) 11454e98e3e1Schristos { 11464b169a6bSchristos const insn_entry *insn; 11474e98e3e1Schristos if (l == NULL && r == NULL) 11484e98e3e1Schristos return 0; 11494e98e3e1Schristos if (l == NULL) 11504e98e3e1Schristos return -1; 11514e98e3e1Schristos if (r == NULL) 11524e98e3e1Schristos return 1; 11534e98e3e1Schristos if (l->insn != r->insn) 11544e98e3e1Schristos return -1; /* somewhat arbitrary at present */ 11554e98e3e1Schristos /* skip this insn */ 11564e98e3e1Schristos insn = l->insn; 11574e98e3e1Schristos while (l != NULL && l->insn == insn) 11584e98e3e1Schristos l = l->next; 11594e98e3e1Schristos while (r != NULL && r->insn == insn) 11604e98e3e1Schristos r = r->next; 11614e98e3e1Schristos } 11624e98e3e1Schristos } 11634e98e3e1Schristos 11644e98e3e1Schristos 11654e98e3e1Schristos 11664e98e3e1Schristos static void 11674e98e3e1Schristos gen_entry_expand_insns (gen_entry *table) 11684e98e3e1Schristos { 11694b169a6bSchristos const decode_table *opcode_rule; 11704e98e3e1Schristos 11714e98e3e1Schristos ASSERT (table->nr_insns >= 1); 11724e98e3e1Schristos 11734e98e3e1Schristos /* determine a valid opcode */ 11744e98e3e1Schristos for (opcode_rule = table->opcode_rule; 11754e98e3e1Schristos opcode_rule != NULL; opcode_rule = opcode_rule->next) 11764e98e3e1Schristos { 11774e98e3e1Schristos char *discard_reason; 11784e98e3e1Schristos if (table->top->model != NULL 11794e98e3e1Schristos && opcode_rule->model_names != NULL 11804e98e3e1Schristos && !filter_is_member (opcode_rule->model_names, 11814e98e3e1Schristos table->top->model->name)) 11824e98e3e1Schristos { 11834e98e3e1Schristos /* the rule isn't applicable to this processor */ 11844e98e3e1Schristos discard_reason = "wrong model"; 11854e98e3e1Schristos } 11864e98e3e1Schristos else if (table->nr_insns == 1 && opcode_rule->conditions == NULL) 11874e98e3e1Schristos { 11884e98e3e1Schristos /* for safety, require a pre-codition when attempting to 11894e98e3e1Schristos apply a rule to a single instruction */ 11904e98e3e1Schristos discard_reason = "need pre-condition when nr-insn == 1"; 11914e98e3e1Schristos } 11924e98e3e1Schristos else if (table->nr_insns == 1 && !opcode_rule->with_duplicates) 11934e98e3e1Schristos { 11944e98e3e1Schristos /* Little point in expanding a single instruction when we're 11954e98e3e1Schristos not duplicating the semantic functions that this table 11964e98e3e1Schristos calls */ 11974e98e3e1Schristos discard_reason = "need duplication with nr-insns == 1"; 11984e98e3e1Schristos } 11994e98e3e1Schristos else 12004e98e3e1Schristos if (!insns_match_format_names 12014e98e3e1Schristos (table->insns, opcode_rule->format_names)) 12024e98e3e1Schristos { 12034e98e3e1Schristos discard_reason = "wrong format name"; 12044e98e3e1Schristos } 12054e98e3e1Schristos else if (!insns_match_nr_words (table->insns, opcode_rule->word_nr + 1)) 12064e98e3e1Schristos { 12074e98e3e1Schristos discard_reason = "wrong nr words"; 12084e98e3e1Schristos } 12094e98e3e1Schristos else if (!table_matches_path (table, opcode_rule->paths)) 12104e98e3e1Schristos { 12114e98e3e1Schristos discard_reason = "path failed"; 12124e98e3e1Schristos } 12134e98e3e1Schristos else 12144e98e3e1Schristos if (!insns_match_conditions (table->insns, opcode_rule->conditions)) 12154e98e3e1Schristos { 12164e98e3e1Schristos discard_reason = "condition failed"; 12174e98e3e1Schristos } 12184e98e3e1Schristos else 12194e98e3e1Schristos { 12204e98e3e1Schristos discard_reason = "no opcode field"; 12214e98e3e1Schristos table->opcode = gen_entry_find_opcode_field (table->insns, 12224e98e3e1Schristos opcode_rule, 12234e98e3e1Schristos table->nr_insns == 1 /*string-only */ 12244e98e3e1Schristos ); 12254e98e3e1Schristos if (table->opcode != NULL) 12264e98e3e1Schristos { 12274e98e3e1Schristos table->opcode_rule = opcode_rule; 12284e98e3e1Schristos break; 12294e98e3e1Schristos } 12304e98e3e1Schristos } 12314e98e3e1Schristos 12324e98e3e1Schristos if (options.trace.rule_rejection) 12334e98e3e1Schristos { 12344e98e3e1Schristos print_gen_entry_path (opcode_rule->line, table, notify); 12354e98e3e1Schristos notify (NULL, ": rule discarded - %s\n", discard_reason); 12364e98e3e1Schristos } 12374e98e3e1Schristos } 12384e98e3e1Schristos 12394e98e3e1Schristos /* did we find anything */ 12404e98e3e1Schristos if (opcode_rule == NULL) 12414e98e3e1Schristos { 12424e98e3e1Schristos /* the decode table failed, this set of instructions haven't 12434e98e3e1Schristos been uniquely identified */ 12444e98e3e1Schristos if (table->nr_insns > 1) 12454e98e3e1Schristos { 12464e98e3e1Schristos print_gen_entry_insns (table, warning, 12474e98e3e1Schristos "was not uniquely decoded", 12484e98e3e1Schristos "decodes to the same entry"); 1249*71f62182Schristos error (NULL, "unrecoverable\n"); 12504e98e3e1Schristos } 12514e98e3e1Schristos return; 12524e98e3e1Schristos } 12534e98e3e1Schristos 12544e98e3e1Schristos /* Determine the number of words that must have been prefetched for 12554e98e3e1Schristos this table to function */ 12564e98e3e1Schristos if (table->parent == NULL) 12574e98e3e1Schristos table->nr_prefetched_words = table->opcode_rule->word_nr + 1; 12584e98e3e1Schristos else if (table->opcode_rule->word_nr + 1 > 12594e98e3e1Schristos table->parent->nr_prefetched_words) 12604e98e3e1Schristos table->nr_prefetched_words = table->opcode_rule->word_nr + 1; 12614e98e3e1Schristos else 12624e98e3e1Schristos table->nr_prefetched_words = table->parent->nr_prefetched_words; 12634e98e3e1Schristos 12644e98e3e1Schristos /* back link what we found to its parent */ 12654e98e3e1Schristos if (table->parent != NULL) 12664e98e3e1Schristos { 12674e98e3e1Schristos ASSERT (table->parent->opcode != NULL); 12684e98e3e1Schristos table->opcode->parent = table->parent->opcode; 12694e98e3e1Schristos } 12704e98e3e1Schristos 12714e98e3e1Schristos /* report the rule being used to expand the instructions */ 12724e98e3e1Schristos if (options.trace.rule_selection) 12734e98e3e1Schristos { 12744e98e3e1Schristos print_gen_entry_path (table->opcode_rule->line, table, notify); 12754e98e3e1Schristos notify (NULL, 12764e98e3e1Schristos ": decode - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d\n", 12774e98e3e1Schristos table->opcode->word_nr, 12784e98e3e1Schristos i2target (options.hi_bit_nr, table->opcode->first), 12794e98e3e1Schristos i2target (options.hi_bit_nr, table->opcode->last), 12804e98e3e1Schristos i2target (options.hi_bit_nr, table->opcode_rule->first), 12814e98e3e1Schristos i2target (options.hi_bit_nr, table->opcode_rule->last), 12824e98e3e1Schristos table->opcode->nr_opcodes, table->nr_entries); 12834e98e3e1Schristos } 12844e98e3e1Schristos 12854e98e3e1Schristos /* expand the raw instructions according to the opcode */ 12864e98e3e1Schristos { 12874e98e3e1Schristos insn_list *entry; 12884e98e3e1Schristos for (entry = table->insns; entry != NULL; entry = entry->next) 12894e98e3e1Schristos { 12904e98e3e1Schristos if (options.trace.insn_expansion) 12914e98e3e1Schristos { 12924e98e3e1Schristos print_gen_entry_path (table->opcode_rule->line, table, notify); 12934e98e3e1Schristos notify (NULL, ": expand - %s.%s\n", 12944e98e3e1Schristos entry->insn->format_name, entry->insn->name); 12954e98e3e1Schristos } 12964e98e3e1Schristos gen_entry_insert_expanding (table, entry->insn); 12974e98e3e1Schristos } 12984e98e3e1Schristos } 12994e98e3e1Schristos 13004e98e3e1Schristos /* dump the results */ 13014e98e3e1Schristos if (options.trace.entries) 13024e98e3e1Schristos { 13034e98e3e1Schristos gen_entry *entry; 13044e98e3e1Schristos for (entry = table->entries; entry != NULL; entry = entry->sibling) 13054e98e3e1Schristos { 13064e98e3e1Schristos insn_list *l; 13074e98e3e1Schristos print_gen_entry_path (table->opcode_rule->line, entry, notify); 13084e98e3e1Schristos notify (NULL, ": %d - entries %d -", 13094e98e3e1Schristos entry->opcode_nr, entry->nr_insns); 13104e98e3e1Schristos for (l = entry->insns; l != NULL; l = l->next) 13114e98e3e1Schristos notify (NULL, " %s.%s", l->insn->format_name, l->insn->name); 13124e98e3e1Schristos notify (NULL, "\n"); 13134e98e3e1Schristos } 13144e98e3e1Schristos } 13154e98e3e1Schristos 13164e98e3e1Schristos /* perform a combine pass if needed */ 13174e98e3e1Schristos if (table->opcode_rule->with_combine) 13184e98e3e1Schristos { 13194e98e3e1Schristos gen_entry *entry; 13204e98e3e1Schristos for (entry = table->entries; entry != NULL; entry = entry->sibling) 13214e98e3e1Schristos { 13224e98e3e1Schristos if (entry->combined_parent == NULL) 13234e98e3e1Schristos { 13244e98e3e1Schristos gen_entry **last = &entry->combined_next; 13254e98e3e1Schristos gen_entry *alt; 13264e98e3e1Schristos for (alt = entry->sibling; alt != NULL; alt = alt->sibling) 13274e98e3e1Schristos { 13284e98e3e1Schristos if (alt->combined_parent == NULL 13294e98e3e1Schristos && insn_list_cmp (entry->insns, alt->insns) == 0) 13304e98e3e1Schristos { 13314e98e3e1Schristos alt->combined_parent = entry; 13324e98e3e1Schristos *last = alt; 13334e98e3e1Schristos last = &alt->combined_next; 13344e98e3e1Schristos } 13354e98e3e1Schristos } 13364e98e3e1Schristos } 13374e98e3e1Schristos } 13384e98e3e1Schristos if (options.trace.combine) 13394e98e3e1Schristos { 13404e98e3e1Schristos int nr_unique = 0; 13414e98e3e1Schristos gen_entry *entry; 13424e98e3e1Schristos for (entry = table->entries; entry != NULL; entry = entry->sibling) 13434e98e3e1Schristos { 13444e98e3e1Schristos if (entry->combined_parent == NULL) 13454e98e3e1Schristos { 13464e98e3e1Schristos insn_list *l; 13474e98e3e1Schristos gen_entry *duplicate; 13484e98e3e1Schristos nr_unique++; 13494e98e3e1Schristos print_gen_entry_path (table->opcode_rule->line, entry, 13504e98e3e1Schristos notify); 13514e98e3e1Schristos for (duplicate = entry->combined_next; duplicate != NULL; 13524e98e3e1Schristos duplicate = duplicate->combined_next) 13534e98e3e1Schristos { 13544e98e3e1Schristos notify (NULL, "+%d", duplicate->opcode_nr); 13554e98e3e1Schristos } 13564e98e3e1Schristos notify (NULL, ": entries %d -", entry->nr_insns); 13574e98e3e1Schristos for (l = entry->insns; l != NULL; l = l->next) 13584e98e3e1Schristos { 13594e98e3e1Schristos notify (NULL, " %s.%s", 13604e98e3e1Schristos l->insn->format_name, l->insn->name); 13614e98e3e1Schristos } 13624e98e3e1Schristos notify (NULL, "\n"); 13634e98e3e1Schristos } 13644e98e3e1Schristos } 13654e98e3e1Schristos print_gen_entry_path (table->opcode_rule->line, table, notify); 13664e98e3e1Schristos notify (NULL, 13674e98e3e1Schristos ": combine - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d, unique %d\n", 13684e98e3e1Schristos table->opcode->word_nr, i2target (options.hi_bit_nr, 13694e98e3e1Schristos table->opcode->first), 13704e98e3e1Schristos i2target (options.hi_bit_nr, table->opcode->last), 13714e98e3e1Schristos i2target (options.hi_bit_nr, table->opcode_rule->first), 13724e98e3e1Schristos i2target (options.hi_bit_nr, table->opcode_rule->last), 13734e98e3e1Schristos table->opcode->nr_opcodes, table->nr_entries, nr_unique); 13744e98e3e1Schristos } 13754e98e3e1Schristos } 13764e98e3e1Schristos 13774e98e3e1Schristos /* Check that the rule did more than re-arange the order of the 13784e98e3e1Schristos instructions */ 13794e98e3e1Schristos { 13804e98e3e1Schristos gen_entry *entry; 13814e98e3e1Schristos for (entry = table->entries; entry != NULL; entry = entry->sibling) 13824e98e3e1Schristos { 13834e98e3e1Schristos if (entry->combined_parent == NULL) 13844e98e3e1Schristos { 13854e98e3e1Schristos if (insn_list_cmp (table->insns, entry->insns) == 0) 13864e98e3e1Schristos { 13874e98e3e1Schristos print_gen_entry_path (table->opcode_rule->line, table, 13884e98e3e1Schristos warning); 13894e98e3e1Schristos warning (NULL, 13904e98e3e1Schristos ": Applying rule just copied all instructions\n"); 13914e98e3e1Schristos print_gen_entry_insns (entry, warning, "Copied", NULL); 1392*71f62182Schristos error (NULL, "unrecoverable\n"); 13934e98e3e1Schristos } 13944e98e3e1Schristos } 13954e98e3e1Schristos } 13964e98e3e1Schristos } 13974e98e3e1Schristos 13984e98e3e1Schristos /* if some form of expanded table, fill in the missing dots */ 13994e98e3e1Schristos switch (table->opcode_rule->gen) 14004e98e3e1Schristos { 14014e98e3e1Schristos case padded_switch_gen: 14024e98e3e1Schristos case array_gen: 14034e98e3e1Schristos case goto_switch_gen: 14044e98e3e1Schristos if (!table->opcode->is_boolean) 14054e98e3e1Schristos { 14064e98e3e1Schristos gen_entry **entry = &table->entries; 14074e98e3e1Schristos gen_entry *illegals = NULL; 14084e98e3e1Schristos gen_entry **last_illegal = &illegals; 14094e98e3e1Schristos int opcode_nr = 0; 14104e98e3e1Schristos while (opcode_nr < table->opcode->nr_opcodes) 14114e98e3e1Schristos { 14124e98e3e1Schristos if ((*entry) == NULL || (*entry)->opcode_nr != opcode_nr) 14134e98e3e1Schristos { 14144e98e3e1Schristos /* missing - insert it under our feet at *entry */ 14154e98e3e1Schristos gen_entry_insert_insn (table, table->top->isa->illegal_insn, table->opcode->word_nr, 0, /* nr_prefetched_words == 0 for invalid */ 14164e98e3e1Schristos opcode_nr, NULL); 14174e98e3e1Schristos ASSERT ((*entry) != NULL); 14184e98e3e1Schristos ASSERT ((*entry)->opcode_nr == opcode_nr); 14194e98e3e1Schristos (*last_illegal) = *entry; 14204e98e3e1Schristos (*last_illegal)->combined_parent = illegals; 14214e98e3e1Schristos last_illegal = &(*last_illegal)->combined_next; 14224e98e3e1Schristos } 14234e98e3e1Schristos entry = &(*entry)->sibling; 14244e98e3e1Schristos opcode_nr++; 14254e98e3e1Schristos } 14264e98e3e1Schristos /* oops, will have pointed the first illegal insn back to 14274e98e3e1Schristos its self. Fix this */ 14284e98e3e1Schristos if (illegals != NULL) 14294e98e3e1Schristos illegals->combined_parent = NULL; 14304e98e3e1Schristos } 14314e98e3e1Schristos break; 14324e98e3e1Schristos case switch_gen: 14334e98e3e1Schristos case invalid_gen: 14344e98e3e1Schristos /* ignore */ 14354e98e3e1Schristos break; 14364e98e3e1Schristos } 14374e98e3e1Schristos 14384e98e3e1Schristos /* and do the same for the newly created sub entries but *only* 14394e98e3e1Schristos expand entries that haven't been combined. */ 14404e98e3e1Schristos { 14414e98e3e1Schristos gen_entry *entry; 14424e98e3e1Schristos for (entry = table->entries; entry != NULL; entry = entry->sibling) 14434e98e3e1Schristos { 14444e98e3e1Schristos if (entry->combined_parent == NULL) 14454e98e3e1Schristos { 14464e98e3e1Schristos gen_entry_expand_insns (entry); 14474e98e3e1Schristos } 14484e98e3e1Schristos } 14494e98e3e1Schristos } 14504e98e3e1Schristos } 14514e98e3e1Schristos 14524e98e3e1Schristos void 14534e98e3e1Schristos gen_tables_expand_insns (gen_table *gen) 14544e98e3e1Schristos { 14554e98e3e1Schristos gen_list *entry; 14564e98e3e1Schristos for (entry = gen->tables; entry != NULL; entry = entry->next) 14574e98e3e1Schristos { 14584e98e3e1Schristos gen_entry_expand_insns (entry->table); 14594e98e3e1Schristos } 14604e98e3e1Schristos } 14614e98e3e1Schristos 14624e98e3e1Schristos 14634e98e3e1Schristos /* create a list of all the semantic functions that need to be 14644e98e3e1Schristos generated. Eliminate any duplicates. Verify that the decode stage 14654e98e3e1Schristos worked. */ 14664e98e3e1Schristos 14674e98e3e1Schristos static void 14684b169a6bSchristos make_gen_semantics_list (lf *file, const gen_entry *entry, int depth, void *data) 14694e98e3e1Schristos { 14704e98e3e1Schristos gen_table *gen = (gen_table *) data; 14714e98e3e1Schristos insn_list *insn; 14724e98e3e1Schristos /* Not interested in an entrie that have been combined into some 14734e98e3e1Schristos other entry at the same level */ 14744e98e3e1Schristos if (entry->combined_parent != NULL) 14754e98e3e1Schristos return; 14764e98e3e1Schristos 14774e98e3e1Schristos /* a leaf should contain exactly one instruction. If not the decode 14784e98e3e1Schristos stage failed. */ 14794e98e3e1Schristos ASSERT (entry->nr_insns == 1); 14804e98e3e1Schristos 14814e98e3e1Schristos /* Enter this instruction into the list of semantic functions. */ 14824e98e3e1Schristos insn = insn_list_insert (&gen->semantics, &gen->nr_semantics, 14834e98e3e1Schristos entry->insns->insn, 14844e98e3e1Schristos entry->expanded_bits, 14854e98e3e1Schristos entry->parent->opcode, 14864e98e3e1Schristos entry->insns->nr_prefetched_words, 14874e98e3e1Schristos merge_duplicate_insns); 14884e98e3e1Schristos /* point the table entry at the real semantic function */ 14894e98e3e1Schristos ASSERT (insn != NULL); 14904e98e3e1Schristos entry->insns->semantic = insn; 14914e98e3e1Schristos } 14924e98e3e1Schristos 14934e98e3e1Schristos 14944e98e3e1Schristos void 14954e98e3e1Schristos gen_tables_expand_semantics (gen_table *gen) 14964e98e3e1Schristos { 14974e98e3e1Schristos gen_list *entry; 14984e98e3e1Schristos for (entry = gen->tables; entry != NULL; entry = entry->next) 14994e98e3e1Schristos { 15004e98e3e1Schristos gen_entry_traverse_tree (NULL, entry->table, 1, /* depth */ 15014e98e3e1Schristos NULL, /* start-handler */ 15024e98e3e1Schristos make_gen_semantics_list, /* leaf-handler */ 15034e98e3e1Schristos NULL, /* end-handler */ 15044e98e3e1Schristos gen); /* data */ 15054e98e3e1Schristos } 15064e98e3e1Schristos } 15074e98e3e1Schristos 15084e98e3e1Schristos 15094e98e3e1Schristos 15104e98e3e1Schristos #ifdef MAIN 15114e98e3e1Schristos 15124e98e3e1Schristos 15134e98e3e1Schristos static void 15144e98e3e1Schristos dump_opcode_field (lf *file, 15154e98e3e1Schristos char *prefix, 15164e98e3e1Schristos opcode_field *field, char *suffix, int levels) 15174e98e3e1Schristos { 15184b169a6bSchristos lf_printf (file, "%s(opcode_field *) %p", prefix, field); 15194e98e3e1Schristos if (levels && field != NULL) 15204e98e3e1Schristos { 15214e98e3e1Schristos lf_indent (file, +1); 15224e98e3e1Schristos lf_printf (file, "\n(first %d)", field->first); 15234e98e3e1Schristos lf_printf (file, "\n(last %d)", field->last); 15244e98e3e1Schristos lf_printf (file, "\n(nr_opcodes %d)", field->nr_opcodes); 15254e98e3e1Schristos lf_printf (file, "\n(is_boolean %d)", field->is_boolean); 15264e98e3e1Schristos lf_printf (file, "\n(boolean_constant %d)", field->boolean_constant); 15274e98e3e1Schristos dump_opcode_field (file, "\n(parent ", field->parent, ")", levels - 1); 15284e98e3e1Schristos lf_indent (file, -1); 15294e98e3e1Schristos } 15304e98e3e1Schristos lf_printf (file, "%s", suffix); 15314e98e3e1Schristos } 15324e98e3e1Schristos 15334e98e3e1Schristos 15344e98e3e1Schristos static void 15354e98e3e1Schristos dump_opcode_bits (lf *file, 15364e98e3e1Schristos char *prefix, opcode_bits *bits, char *suffix, int levels) 15374e98e3e1Schristos { 15384b169a6bSchristos lf_printf (file, "%s(opcode_bits *) %p", prefix, bits); 15394e98e3e1Schristos 15404e98e3e1Schristos if (levels && bits != NULL) 15414e98e3e1Schristos { 15424e98e3e1Schristos lf_indent (file, +1); 15434e98e3e1Schristos lf_printf (file, "\n(value %d)", bits->value); 15444e98e3e1Schristos dump_opcode_field (file, "\n(opcode ", bits->opcode, ")", 0); 15454e98e3e1Schristos dump_insn_field (file, "\n(field ", bits->field, ")"); 15464e98e3e1Schristos dump_opcode_bits (file, "\n(next ", bits->next, ")", levels - 1); 15474e98e3e1Schristos lf_indent (file, -1); 15484e98e3e1Schristos } 15494e98e3e1Schristos lf_printf (file, "%s", suffix); 15504e98e3e1Schristos } 15514e98e3e1Schristos 15524e98e3e1Schristos 15534e98e3e1Schristos 15544e98e3e1Schristos static void 15554e98e3e1Schristos dump_insn_list (lf *file, char *prefix, insn_list *entry, char *suffix) 15564e98e3e1Schristos { 15574b169a6bSchristos lf_printf (file, "%s(insn_list *) %p", prefix, entry); 15584e98e3e1Schristos 15594e98e3e1Schristos if (entry != NULL) 15604e98e3e1Schristos { 15614e98e3e1Schristos lf_indent (file, +1); 15624e98e3e1Schristos dump_insn_entry (file, "\n(insn ", entry->insn, ")"); 15634b169a6bSchristos lf_printf (file, "\n(next %p)", entry->next); 15644e98e3e1Schristos lf_indent (file, -1); 15654e98e3e1Schristos } 15664e98e3e1Schristos lf_printf (file, "%s", suffix); 15674e98e3e1Schristos } 15684e98e3e1Schristos 15694e98e3e1Schristos 15704e98e3e1Schristos static void 15714e98e3e1Schristos dump_insn_word_entry_list_entries (lf *file, 15724e98e3e1Schristos char *prefix, 15734e98e3e1Schristos insn_list *entry, char *suffix) 15744e98e3e1Schristos { 15754e98e3e1Schristos lf_printf (file, "%s", prefix); 15764e98e3e1Schristos while (entry != NULL) 15774e98e3e1Schristos { 15784e98e3e1Schristos dump_insn_list (file, "\n(", entry, ")"); 15794e98e3e1Schristos entry = entry->next; 15804e98e3e1Schristos } 15814e98e3e1Schristos lf_printf (file, "%s", suffix); 15824e98e3e1Schristos } 15834e98e3e1Schristos 15844e98e3e1Schristos 15854e98e3e1Schristos static void 15864e98e3e1Schristos dump_gen_entry (lf *file, 15874e98e3e1Schristos char *prefix, gen_entry *table, char *suffix, int levels) 15884e98e3e1Schristos { 15894e98e3e1Schristos 15904b169a6bSchristos lf_printf (file, "%s(gen_entry *) %p", prefix, table); 15914e98e3e1Schristos 15924e98e3e1Schristos if (levels && table !=NULL) 15934e98e3e1Schristos { 15944e98e3e1Schristos 15954e98e3e1Schristos lf_indent (file, +1); 15964e98e3e1Schristos lf_printf (file, "\n(opcode_nr %d)", table->opcode_nr); 15974e98e3e1Schristos lf_printf (file, "\n(word_nr %d)", table->word_nr); 15984e98e3e1Schristos dump_opcode_bits (file, "\n(expanded_bits ", table->expanded_bits, ")", 15994e98e3e1Schristos -1); 16004e98e3e1Schristos lf_printf (file, "\n(nr_insns %d)", table->nr_insns); 16014e98e3e1Schristos dump_insn_word_entry_list_entries (file, "\n(insns ", table->insns, 16024e98e3e1Schristos ")"); 16034e98e3e1Schristos dump_decode_rule (file, "\n(opcode_rule ", table->opcode_rule, ")"); 16044e98e3e1Schristos dump_opcode_field (file, "\n(opcode ", table->opcode, ")", 0); 16054e98e3e1Schristos lf_printf (file, "\n(nr_entries %d)", table->nr_entries); 16064e98e3e1Schristos dump_gen_entry (file, "\n(entries ", table->entries, ")", 16074e98e3e1Schristos table->nr_entries); 16084e98e3e1Schristos dump_gen_entry (file, "\n(sibling ", table->sibling, ")", levels - 1); 16094e98e3e1Schristos dump_gen_entry (file, "\n(parent ", table->parent, ")", 0); 16104e98e3e1Schristos lf_indent (file, -1); 16114e98e3e1Schristos } 16124e98e3e1Schristos lf_printf (file, "%s", suffix); 16134e98e3e1Schristos } 16144e98e3e1Schristos 16154e98e3e1Schristos static void 16164e98e3e1Schristos dump_gen_list (lf *file, 16174e98e3e1Schristos char *prefix, gen_list *entry, char *suffix, int levels) 16184e98e3e1Schristos { 16194e98e3e1Schristos while (entry != NULL) 16204e98e3e1Schristos { 16214b169a6bSchristos lf_printf (file, "%s(gen_list *) %p", prefix, entry); 16224e98e3e1Schristos dump_gen_entry (file, "\n(", entry->table, ")", levels); 16234b169a6bSchristos lf_printf (file, "\n(next (gen_list *) %p)", entry->next); 16244e98e3e1Schristos lf_printf (file, "%s", suffix); 16254e98e3e1Schristos } 16264e98e3e1Schristos } 16274e98e3e1Schristos 16284e98e3e1Schristos 16294e98e3e1Schristos static void 16304e98e3e1Schristos dump_gen_table (lf *file, 16314e98e3e1Schristos char *prefix, gen_table *gen, char *suffix, int levels) 16324e98e3e1Schristos { 16334b169a6bSchristos lf_printf (file, "%s(gen_table *) %p", prefix, gen); 16344b169a6bSchristos lf_printf (file, "\n(isa (insn_table *) %p)", gen->isa); 16354b169a6bSchristos lf_printf (file, "\n(rules (decode_table *) %p)", gen->rules); 16364e98e3e1Schristos dump_gen_list (file, "\n(", gen->tables, ")", levels); 16374e98e3e1Schristos lf_printf (file, "%s", suffix); 16384e98e3e1Schristos } 16394e98e3e1Schristos 16404e98e3e1Schristos 16414e98e3e1Schristos igen_options options; 16424e98e3e1Schristos 16434e98e3e1Schristos int 16444e98e3e1Schristos main (int argc, char **argv) 16454e98e3e1Schristos { 16464e98e3e1Schristos decode_table *decode_rules; 16474e98e3e1Schristos insn_table *instructions; 16484e98e3e1Schristos gen_table *gen; 16494e98e3e1Schristos lf *l; 16504e98e3e1Schristos 16514e98e3e1Schristos if (argc != 7) 16524e98e3e1Schristos error (NULL, 16534e98e3e1Schristos "Usage: insn <filter-in> <hi-bit-nr> <insn-bit-size> <widths> <decode-table> <insn-table>\n"); 16544e98e3e1Schristos 16554b169a6bSchristos INIT_OPTIONS (); 16564e98e3e1Schristos 16574e98e3e1Schristos filter_parse (&options.flags_filter, argv[1]); 16584e98e3e1Schristos 16594e98e3e1Schristos options.hi_bit_nr = a2i (argv[2]); 16604e98e3e1Schristos options.insn_bit_size = a2i (argv[3]); 16614e98e3e1Schristos options.insn_specifying_widths = a2i (argv[4]); 16624e98e3e1Schristos ASSERT (options.hi_bit_nr < options.insn_bit_size); 16634e98e3e1Schristos 16644e98e3e1Schristos instructions = load_insn_table (argv[6], NULL); 16654e98e3e1Schristos decode_rules = load_decode_table (argv[5]); 16664e98e3e1Schristos gen = make_gen_tables (instructions, decode_rules); 16674e98e3e1Schristos 16684e98e3e1Schristos gen_tables_expand_insns (gen); 16694e98e3e1Schristos 16704e98e3e1Schristos l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn"); 16714e98e3e1Schristos 16724e98e3e1Schristos dump_gen_table (l, "(", gen, ")\n", -1); 16734e98e3e1Schristos return 0; 16744e98e3e1Schristos } 16754e98e3e1Schristos 16764e98e3e1Schristos #endif 1677