xref: /netbsd-src/external/gpl3/gdb/dist/sim/igen/gen.c (revision 71f621822dbfd5073a314948bec169b7bb05f7be)
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