1/*  This file is part of the program psim.
2
3    Copyright 1994, 1995, 1996, 2003 Andrew Cagney
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19    */
20
21
22#include "misc.h"
23#include "lf.h"
24#include "table.h"
25#include "filter.h"
26#include "ld-decode.h"
27#include "ld-cache.h"
28#include "ld-insn.h"
29
30#include "igen.h"
31
32static void
33update_depth(insn_table *entry,
34	     lf *file,
35	     void *data,
36	     insn *instruction,
37	     int depth)
38{
39  int *max_depth = (int*)data;
40  if (*max_depth < depth)
41    *max_depth = depth;
42}
43
44
45int
46insn_table_depth(insn_table *table)
47{
48  int depth = 0;
49  insn_table_traverse_tree(table,
50			   NULL,
51			   &depth,
52			   1,
53			   NULL, /*start*/
54			   update_depth,
55			   NULL, /*end*/
56			   NULL); /*padding*/
57  return depth;
58}
59
60
61static insn_fields *
62parse_insn_format(table_entry *entry,
63		  char *format)
64{
65  char *chp;
66  insn_fields *fields = ZALLOC(insn_fields);
67
68  /* create a leading sentinal */
69  fields->first = ZALLOC(insn_field);
70  fields->first->first = -1;
71  fields->first->last = -1;
72  fields->first->width = 0;
73
74  /* and a trailing sentinal */
75  fields->last = ZALLOC(insn_field);
76  fields->last->first = insn_bit_size;
77  fields->last->last = insn_bit_size;
78  fields->last->width = 0;
79
80  /* link them together */
81  fields->first->next = fields->last;
82  fields->last->prev = fields->first;
83
84  /* now work through the formats */
85  chp = format;
86
87  while (*chp != '\0') {
88    char *start_pos;
89    char *start_val;
90    int strlen_val;
91    int strlen_pos;
92    insn_field *new_field;
93
94    /* sanity check */
95    if (!isdigit(*chp)) {
96      error("%s:%d: missing position field at `%s'\n",
97	    entry->file_name, entry->line_nr, chp);
98    }
99
100    /* break out the bit position */
101    start_pos = chp;
102    while (isdigit(*chp))
103      chp++;
104    strlen_pos = chp - start_pos;
105    if (*chp == '.' && strlen_pos > 0)
106      chp++;
107    else {
108      error("%s:%d: missing field value at %s\n",
109	    entry->file_name, entry->line_nr, chp);
110      break;
111    }
112
113    /* break out the value */
114    start_val = chp;
115    while ((*start_val == '/' && *chp == '/')
116	   || (isdigit(*start_val) && isdigit(*chp))
117	   || (isalpha(*start_val) && (isalnum(*chp) || *chp == '_')))
118      chp++;
119    strlen_val = chp - start_val;
120    if (*chp == ',')
121      chp++;
122    else if (*chp != '\0' || strlen_val == 0) {
123      error("%s:%d: missing field terminator at %s\n",
124	    entry->file_name, entry->line_nr, chp);
125      break;
126    }
127
128    /* create a new field and insert it */
129    new_field = ZALLOC(insn_field);
130    new_field->next = fields->last;
131    new_field->prev = fields->last->prev;
132    new_field->next->prev = new_field;
133    new_field->prev->next = new_field;
134
135    /* the value */
136    new_field->val_string = (char*)zalloc(strlen_val+1);
137    strncpy(new_field->val_string, start_val, strlen_val);
138    if (isdigit(*new_field->val_string)) {
139      new_field->val_int = a2i(new_field->val_string);
140      new_field->is_int = 1;
141    }
142    else if (new_field->val_string[0] == '/') {
143      new_field->is_slash = 1;
144    }
145    else {
146      new_field->is_string = 1;
147    }
148
149    /* the pos */
150    new_field->pos_string = (char*)zalloc(strlen_pos+1);
151    strncpy(new_field->pos_string, start_pos, strlen_pos);
152    new_field->first = target_a2i(hi_bit_nr, new_field->pos_string);
153    new_field->last = new_field->next->first - 1; /* guess */
154    new_field->width = new_field->last - new_field->first + 1; /* guess */
155    new_field->prev->last = new_field->first-1; /*fix*/
156    new_field->prev->width = new_field->first - new_field->prev->first; /*fix*/
157  }
158
159  /* fiddle first/last so that the sentinals `disapear' */
160  ASSERT(fields->first->last < 0);
161  ASSERT(fields->last->first >= insn_bit_size);
162  fields->first = fields->first->next;
163  fields->last = fields->last->prev;
164
165  /* now go over this again, pointing each bit position at a field
166     record */
167  {
168    int i;
169    insn_field *field;
170    field = fields->first;
171    for (i = 0; i < insn_bit_size; i++) {
172      while (field->last < i)
173	field = field->next;
174      fields->bits[i] = field;
175    }
176  }
177
178  /* go over each of the fields, and compute a `value' for the insn */
179  {
180    insn_field *field;
181    fields->value = 0;
182    for (field = fields->first;
183	 field->last < insn_bit_size;
184	 field = field->next) {
185      fields->value <<= field->width;
186      if (field->is_int)
187	fields->value |= field->val_int;
188    }
189  }
190  return fields;
191}
192
193
194void
195parse_include_entry (table *file,
196                     table_entry *file_entry,
197		     filter *filters,
198		     table_include *includes)
199{
200  /* parse the include file_entry */
201  if (file_entry->nr_fields < 4)
202    error ("Incorrect nr fields for include record\n");
203  /* process it */
204  if (!is_filtered_out(file_entry->fields[include_flags], filters))
205    {
206      table_push (file, includes,
207                file_entry->fields[include_path],
208		file_entry->nr_fields, file_entry->nr_fields);
209    }
210}
211
212static void
213model_table_insert(insn_table *table,
214		   table_entry *file_entry)
215{
216  int len;
217
218  /* create a new model */
219  model *new_model = ZALLOC(model);
220
221  new_model->name = file_entry->fields[model_identifer];
222  new_model->printable_name = file_entry->fields[model_name];
223  new_model->insn_default = file_entry->fields[model_default];
224
225  while (*new_model->insn_default && isspace(*new_model->insn_default))
226    new_model->insn_default++;
227
228  len = strlen(new_model->insn_default);
229  if (max_model_fields_len < len)
230    max_model_fields_len = len;
231
232  /* append it to the end of the model list */
233  if (last_model)
234    last_model->next = new_model;
235  else
236    models = new_model;
237  last_model = new_model;
238}
239
240static void
241model_table_insert_specific(insn_table *table,
242			    table_entry *file_entry,
243			    insn **start_ptr,
244			    insn **end_ptr)
245{
246  insn *ptr = ZALLOC(insn);
247  ptr->file_entry = file_entry;
248  if (*end_ptr)
249    (*end_ptr)->next = ptr;
250  else
251    (*start_ptr) = ptr;
252  (*end_ptr) = ptr;
253}
254
255
256static void
257insn_table_insert_function(insn_table *table,
258			   table_entry *file_entry)
259{
260  /* create a new function */
261  insn *new_function = ZALLOC(insn);
262  new_function->file_entry = file_entry;
263
264  /* append it to the end of the function list */
265  if (table->last_function)
266    table->last_function->next = new_function;
267  else
268    table->functions = new_function;
269  table->last_function = new_function;
270}
271
272extern void
273insn_table_insert_insn(insn_table *table,
274		       table_entry *file_entry,
275		       insn_fields *fields)
276{
277  insn **ptr_to_cur_insn = &table->insns;
278  insn *cur_insn = *ptr_to_cur_insn;
279  table_model_entry *insn_model_ptr;
280  model *model_ptr;
281
282  /* create a new instruction */
283  insn *new_insn = ZALLOC(insn);
284  new_insn->file_entry = file_entry;
285  new_insn->fields = fields;
286
287  /* Check out any model information returned to make sure the model
288     is correct.  */
289  for(insn_model_ptr = file_entry->model_first; insn_model_ptr; insn_model_ptr = insn_model_ptr->next) {
290    char *name = insn_model_ptr->fields[insn_model_name];
291    int len = strlen (insn_model_ptr->fields[insn_model_fields]);
292
293    while (len > 0 && isspace(*insn_model_ptr->fields[insn_model_fields])) {
294      len--;
295      insn_model_ptr->fields[insn_model_fields]++;
296    }
297
298    if (max_model_fields_len < len)
299      max_model_fields_len = len;
300
301    for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
302      if (strcmp(name, model_ptr->printable_name) == 0) {
303
304	/* Replace the name field with that of the global model, so that when we
305	   want to print it out, we can just compare pointers.  */
306	insn_model_ptr->fields[insn_model_name] = model_ptr->printable_name;
307	break;
308      }
309    }
310
311    if (!model_ptr)
312      error("%s:%d: machine model `%s' was not known about\n",
313	    file_entry->file_name, file_entry->line_nr, name);
314  }
315
316  /* insert it according to the order of the fields */
317  while (cur_insn != NULL
318	 && new_insn->fields->value >= cur_insn->fields->value) {
319    ptr_to_cur_insn = &cur_insn->next;
320    cur_insn = *ptr_to_cur_insn;
321  }
322
323  new_insn->next = cur_insn;
324  *ptr_to_cur_insn = new_insn;
325
326  table->nr_insn++;
327}
328
329
330
331insn_table *
332load_insn_table(const char *file_name,
333		decode_table *decode_rules,
334		filter *filters,
335		table_include *includes,
336		cache_table **cache_rules)
337{
338  table *file = table_open(file_name, nr_insn_table_fields, nr_insn_model_table_fields);
339  insn_table *table = ZALLOC(insn_table);
340  table_entry *file_entry;
341  table->opcode_rule = decode_rules;
342
343  while ((file_entry = table_entry_read(file)) != NULL) {
344    if (it_is("function", file_entry->fields[insn_flags])
345	|| it_is("internal", file_entry->fields[insn_flags])) {
346      insn_table_insert_function(table, file_entry);
347    }
348    else if ((it_is("function", file_entry->fields[insn_form])
349	      || it_is("internal", file_entry->fields[insn_form]))
350	     && !is_filtered_out(file_entry->fields[insn_flags], filters)) {
351      /* Ok, this is evil.  Need to convert a new style function into
352         an old style function.  Construct an old style table and then
353         copy it back.  */
354      char *fields[nr_insn_table_fields];
355      memset (fields, 0, sizeof fields);
356      fields[insn_flags] = file_entry->fields[insn_form];
357      fields[function_type] = file_entry->fields[insn_name];
358      fields[function_name] = file_entry->fields[insn_comment];
359      fields[function_param] = file_entry->fields[insn_field_6];
360      memcpy (file_entry->fields, fields,
361	      sizeof (fields[0]) * file_entry->nr_fields);
362      insn_table_insert_function(table, file_entry);
363#if 0
364      ":" "..."
365       ":" <filter-flags>
366       ":" <filter-models>
367       ":" <typedef>
368       ":" <name>
369       [ ":" <parameter-list> ]
370       <nl>
371       [ <function-model> ]
372       <code-block>
373#endif
374    }
375    else if (it_is("model", file_entry->fields[insn_flags])) {
376      model_table_insert(table, file_entry);
377    }
378    else if (it_is("model-macro", file_entry->fields[insn_flags])) {
379      model_table_insert_specific(table, file_entry, &model_macros, &last_model_macro);
380    }
381    else if (it_is("model-function", file_entry->fields[insn_flags])) {
382      model_table_insert_specific(table, file_entry, &model_functions, &last_model_function);
383    }
384    else if (it_is("model-internal", file_entry->fields[insn_flags])) {
385      model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal);
386    }
387    else if (it_is("model-static", file_entry->fields[insn_flags])) {
388      model_table_insert_specific(table, file_entry, &model_static, &last_model_static);
389    }
390    else if (it_is("model-data", file_entry->fields[insn_flags])) {
391      model_table_insert_specific(table, file_entry, &model_data, &last_model_data);
392    }
393    else if (it_is("include", file_entry->fields[insn_form])
394             && !is_filtered_out(file_entry->fields[insn_flags], filters)) {
395      parse_include_entry (file, file_entry, filters, includes);
396    }
397    else if ((it_is("cache", file_entry->fields[insn_form])
398	      || it_is("compute", file_entry->fields[insn_form])
399	      || it_is("scratch", file_entry->fields[insn_form]))
400	     && !is_filtered_out(file_entry->fields[insn_flags], filters)) {
401      append_cache_rule (cache_rules,
402			 file_entry->fields[insn_form], /* type */
403			 file_entry->fields[cache_name],
404			 file_entry->fields[cache_derived_name],
405			 file_entry->fields[cache_type_def],
406			 file_entry->fields[cache_expression],
407			 file_entry);
408    }
409    else {
410      insn_fields *fields;
411      /* skip instructions that aren't relevant to the mode */
412      if (is_filtered_out(file_entry->fields[insn_flags], filters)) {
413	fprintf(stderr, "Dropping %s - %s\n",
414		file_entry->fields[insn_name],
415		file_entry->fields[insn_flags]);
416      }
417      else {
418	/* create/insert the new instruction */
419	fields = parse_insn_format(file_entry,
420				   file_entry->fields[insn_format]);
421	insn_table_insert_insn(table, file_entry, fields);
422      }
423    }
424  }
425  return table;
426}
427
428
429extern void
430insn_table_traverse_tree(insn_table *table,
431			 lf *file,
432			 void *data,
433			 int depth,
434			 leaf_handler *start,
435			 insn_handler *leaf,
436			 leaf_handler *end,
437			 padding_handler *padding)
438{
439  insn_table *entry;
440  int entry_nr;
441
442  ASSERT(table != NULL
443	 && table->opcode != NULL
444	 && table->nr_entries > 0
445	 && table->entries != 0);
446
447  if (start != NULL && depth >= 0)
448    start(table, file, data, depth);
449
450  for (entry_nr = 0, entry = table->entries;
451       entry_nr < (table->opcode->is_boolean
452		   ? 2
453		   : (1 << (table->opcode->last - table->opcode->first + 1)));
454       entry_nr ++) {
455    if (entry == NULL
456	|| (!table->opcode->is_boolean
457	    && entry_nr < entry->opcode_nr)) {
458      if (padding != NULL && depth >= 0)
459	padding(table, file, data, depth, entry_nr);
460    }
461    else {
462      ASSERT(entry != NULL && (entry->opcode_nr == entry_nr
463			       || table->opcode->is_boolean));
464      if (entry->opcode != NULL && depth != 0) {
465	insn_table_traverse_tree(entry, file, data, depth+1,
466				 start, leaf, end, padding);
467      }
468      else if (depth >= 0) {
469	if (leaf != NULL)
470	  leaf(entry, file, data, entry->insns, depth);
471      }
472      entry = entry->sibling;
473    }
474  }
475  if (end != NULL && depth >= 0)
476    end(table, file, data, depth);
477}
478
479
480extern void
481insn_table_traverse_function(insn_table *table,
482			     lf *file,
483			     void *data,
484			     function_handler *leaf)
485{
486  insn *function;
487  for (function = table->functions;
488       function != NULL;
489       function = function->next) {
490    leaf(table, file, data, function->file_entry);
491  }
492}
493
494extern void
495insn_table_traverse_insn(insn_table *table,
496			 lf *file,
497			 void *data,
498			 insn_handler *handler)
499{
500  insn *instruction;
501  for (instruction = table->insns;
502       instruction != NULL;
503       instruction = instruction->next) {
504    handler(table, file, data, instruction, 0);
505  }
506}
507
508
509/****************************************************************/
510
511typedef enum {
512  field_constant_int = 1,
513  field_constant_slash = 2,
514  field_constant_string = 3
515} constant_field_types;
516
517
518static int
519insn_field_is_constant(insn_field *field,
520		       decode_table *rule)
521{
522  /* field is an integer */
523  if (field->is_int)
524    return field_constant_int;
525  /* field is `/' and treating that as a constant */
526  if (field->is_slash && rule->force_slash)
527    return field_constant_slash;
528  /* field, though variable is on the list */
529  if (field->is_string && rule->force_expansion != NULL) {
530    char *forced_fields = rule->force_expansion;
531    while (*forced_fields != '\0') {
532      int field_len;
533      char *end = strchr(forced_fields, ',');
534      if (end == NULL)
535	field_len = strlen(forced_fields);
536      else
537	field_len = end-forced_fields;
538      if (strncmp(forced_fields, field->val_string, field_len) == 0
539	  && field->val_string[field_len] == '\0')
540	return field_constant_string;
541      forced_fields += field_len;
542      if (*forced_fields == ',')
543	forced_fields++;
544    }
545  }
546  return 0;
547}
548
549
550static opcode_field *
551insn_table_find_opcode_field(insn *insns,
552			     decode_table *rule,
553			     int string_only)
554{
555  opcode_field *curr_opcode = ZALLOC(opcode_field);
556  insn *entry;
557  ASSERT(rule);
558
559  curr_opcode->first = insn_bit_size;
560  curr_opcode->last = -1;
561  for (entry = insns; entry != NULL; entry = entry->next) {
562    insn_fields *fields = entry->fields;
563    opcode_field new_opcode;
564
565    /* find a start point for the opcode field */
566    new_opcode.first = rule->first;
567    while (new_opcode.first <= rule->last
568	   && (!string_only
569	       || insn_field_is_constant(fields->bits[new_opcode.first],
570					 rule) != field_constant_string)
571	   && (string_only
572	       || !insn_field_is_constant(fields->bits[new_opcode.first],
573					  rule)))
574      new_opcode.first = fields->bits[new_opcode.first]->last + 1;
575    ASSERT(new_opcode.first > rule->last
576	   || (string_only
577	       && insn_field_is_constant(fields->bits[new_opcode.first],
578					 rule) == field_constant_string)
579	   || (!string_only
580	       && insn_field_is_constant(fields->bits[new_opcode.first],
581					 rule)));
582
583    /* find the end point for the opcode field */
584    new_opcode.last = rule->last;
585    while (new_opcode.last >= rule->first
586	   && (!string_only
587	       || insn_field_is_constant(fields->bits[new_opcode.last],
588					 rule) != field_constant_string)
589	   && (string_only
590	       || !insn_field_is_constant(fields->bits[new_opcode.last],
591					  rule)))
592      new_opcode.last = fields->bits[new_opcode.last]->first - 1;
593    ASSERT(new_opcode.last < rule->first
594	   || (string_only
595	       && insn_field_is_constant(fields->bits[new_opcode.last],
596					 rule) == field_constant_string)
597	   || (!string_only
598	       && insn_field_is_constant(fields->bits[new_opcode.last],
599					 rule)));
600
601    /* now see if our current opcode needs expanding */
602    if (new_opcode.first <= rule->last
603	&& curr_opcode->first > new_opcode.first)
604      curr_opcode->first = new_opcode.first;
605    if (new_opcode.last >= rule->first
606	&& curr_opcode->last < new_opcode.last)
607      curr_opcode->last = new_opcode.last;
608
609  }
610
611  /* was any thing interesting found? */
612  if (curr_opcode->first > rule->last) {
613    ASSERT(curr_opcode->last < rule->first);
614    return NULL;
615  }
616  ASSERT(curr_opcode->last >= rule->first);
617  ASSERT(curr_opcode->first <= rule->last);
618
619  /* if something was found, check it includes the forced field range */
620  if (!string_only
621      && curr_opcode->first > rule->force_first) {
622    curr_opcode->first = rule->force_first;
623  }
624  if (!string_only
625      && curr_opcode->last < rule->force_last) {
626    curr_opcode->last = rule->force_last;
627  }
628  /* handle special case elminating any need to do shift after mask */
629  if (string_only
630      && rule->force_last == insn_bit_size-1) {
631    curr_opcode->last = insn_bit_size-1;
632  }
633
634  /* handle any special cases */
635  switch (rule->type) {
636  case normal_decode_rule:
637    /* let the above apply */
638    break;
639  case expand_forced_rule:
640    /* expand a limited nr of bits, ignoring the rest */
641    curr_opcode->first = rule->force_first;
642    curr_opcode->last = rule->force_last;
643    break;
644  case boolean_rule:
645    curr_opcode->is_boolean = 1;
646    curr_opcode->boolean_constant = rule->special_constant;
647    break;
648  default:
649    error("Something is going wrong\n");
650  }
651
652  return curr_opcode;
653}
654
655
656static void
657insn_table_insert_expanded(insn_table *table,
658			   insn *old_insn,
659			   int new_opcode_nr,
660			   insn_bits *new_bits)
661{
662  insn_table **ptr_to_cur_entry = &table->entries;
663  insn_table *cur_entry = *ptr_to_cur_entry;
664
665  /* find the new table for this entry */
666  while (cur_entry != NULL
667	 && cur_entry->opcode_nr < new_opcode_nr) {
668    ptr_to_cur_entry = &cur_entry->sibling;
669    cur_entry = *ptr_to_cur_entry;
670  }
671
672  if (cur_entry == NULL || cur_entry->opcode_nr != new_opcode_nr) {
673    insn_table *new_entry = ZALLOC(insn_table);
674    new_entry->opcode_nr = new_opcode_nr;
675    new_entry->expanded_bits = new_bits;
676    new_entry->opcode_rule = table->opcode_rule->next;
677    new_entry->sibling = cur_entry;
678    new_entry->parent = table;
679    *ptr_to_cur_entry = new_entry;
680    cur_entry = new_entry;
681    table->nr_entries++;
682  }
683  /* ASSERT new_bits == cur_entry bits */
684  ASSERT(cur_entry != NULL && cur_entry->opcode_nr == new_opcode_nr);
685  insn_table_insert_insn(cur_entry,
686			 old_insn->file_entry,
687			 old_insn->fields);
688}
689
690static void
691insn_table_expand_opcode(insn_table *table,
692			 insn *instruction,
693			 int field_nr,
694			 int opcode_nr,
695			 insn_bits *bits)
696{
697
698  if (field_nr > table->opcode->last) {
699    insn_table_insert_expanded(table, instruction, opcode_nr, bits);
700  }
701  else {
702    insn_field *field = instruction->fields->bits[field_nr];
703    if (field->is_int || field->is_slash) {
704      ASSERT(field->first >= table->opcode->first
705	     && field->last <= table->opcode->last);
706      insn_table_expand_opcode(table, instruction, field->last+1,
707			       ((opcode_nr << field->width) + field->val_int),
708			       bits);
709    }
710    else {
711      int val;
712      int last_pos = ((field->last < table->opcode->last)
713			? field->last : table->opcode->last);
714      int first_pos = ((field->first > table->opcode->first)
715			 ? field->first : table->opcode->first);
716      int width = last_pos - first_pos + 1;
717      int last_val = (table->opcode->is_boolean
718		      ? 2 : (1 << width));
719      for (val = 0; val < last_val; val++) {
720	insn_bits *new_bits = ZALLOC(insn_bits);
721	new_bits->field = field;
722	new_bits->value = val;
723	new_bits->last = bits;
724	new_bits->opcode = table->opcode;
725	insn_table_expand_opcode(table, instruction, last_pos+1,
726				 ((opcode_nr << width) | val),
727				 new_bits);
728      }
729    }
730  }
731}
732
733static void
734insn_table_insert_expanding(insn_table *table,
735			    insn *entry)
736{
737  insn_table_expand_opcode(table,
738			   entry,
739			   table->opcode->first,
740			   0,
741			   table->expanded_bits);
742}
743
744
745extern void
746insn_table_expand_insns(insn_table *table)
747{
748
749  ASSERT(table->nr_insn >= 1);
750
751  /* determine a valid opcode */
752  while (table->opcode_rule) {
753    /* specials only for single instructions */
754    if ((table->nr_insn > 1
755	 && table->opcode_rule->special_mask == 0
756	 && table->opcode_rule->type == normal_decode_rule)
757	|| (table->nr_insn == 1
758	    && table->opcode_rule->special_mask != 0
759	    && ((table->insns->fields->value
760		 & table->opcode_rule->special_mask)
761		== table->opcode_rule->special_value))
762	|| (generate_expanded_instructions
763	    && table->opcode_rule->special_mask == 0
764	    && table->opcode_rule->type == normal_decode_rule))
765      table->opcode =
766	insn_table_find_opcode_field(table->insns,
767				     table->opcode_rule,
768				     table->nr_insn == 1/*string*/
769				     );
770    if (table->opcode != NULL)
771      break;
772    table->opcode_rule = table->opcode_rule->next;
773  }
774
775  /* did we find anything */
776  if (table->opcode == NULL) {
777    return;
778  }
779  ASSERT(table->opcode != NULL);
780
781  /* back link what we found to its parent */
782  if (table->parent != NULL) {
783    ASSERT(table->parent->opcode != NULL);
784    table->opcode->parent = table->parent->opcode;
785  }
786
787  /* expand the raw instructions according to the opcode */
788  {
789    insn *entry;
790    for (entry = table->insns; entry != NULL; entry = entry->next) {
791      insn_table_insert_expanding(table, entry);
792    }
793  }
794
795  /* and do the same for the sub entries */
796  {
797    insn_table *entry;
798    for (entry = table->entries; entry != NULL; entry =  entry->sibling) {
799      insn_table_expand_insns(entry);
800    }
801  }
802}
803
804
805
806
807#ifdef MAIN
808
809static void
810dump_insn_field(insn_field *field,
811		int indent)
812{
813
814  printf("(insn_field*)0x%x\n", (unsigned)field);
815
816  dumpf(indent, "(first %d)\n", field->first);
817
818  dumpf(indent, "(last %d)\n", field->last);
819
820  dumpf(indent, "(width %d)\n", field->width);
821
822  if (field->is_int)
823    dumpf(indent, "(is_int %d)\n", field->val_int);
824
825  if (field->is_slash)
826    dumpf(indent, "(is_slash)\n");
827
828  if (field->is_string)
829    dumpf(indent, "(is_string `%s')\n", field->val_string);
830
831  dumpf(indent, "(next 0x%x)\n", field->next);
832
833  dumpf(indent, "(prev 0x%x)\n", field->prev);
834
835
836}
837
838static void
839dump_insn_fields(insn_fields *fields,
840		 int indent)
841{
842  int i;
843
844  printf("(insn_fields*)%p\n", fields);
845
846  dumpf(indent, "(first 0x%x)\n", fields->first);
847  dumpf(indent, "(last 0x%x)\n", fields->last);
848
849  dumpf(indent, "(value 0x%x)\n", fields->value);
850
851  for (i = 0; i < insn_bit_size; i++) {
852    dumpf(indent, "(bits[%d] ", i, fields->bits[i]);
853    dump_insn_field(fields->bits[i], indent+1);
854    dumpf(indent, " )\n");
855  }
856
857}
858
859
860static void
861dump_opcode_field(opcode_field *field, int indent, int levels)
862{
863  printf("(opcode_field*)%p\n", field);
864  if (levels && field != NULL) {
865    dumpf(indent, "(first %d)\n", field->first);
866    dumpf(indent, "(last %d)\n", field->last);
867    dumpf(indent, "(is_boolean %d)\n", field->is_boolean);
868    dumpf(indent, "(parent ");
869    dump_opcode_field(field->parent, indent, levels-1);
870  }
871}
872
873
874static void
875dump_insn_bits(insn_bits *bits, int indent, int levels)
876{
877  printf("(insn_bits*)%p\n", bits);
878
879  if (levels && bits != NULL) {
880    dumpf(indent, "(value %d)\n", bits->value);
881    dumpf(indent, "(opcode ");
882    dump_opcode_field(bits->opcode, indent+1, 0);
883    dumpf(indent, " )\n");
884    dumpf(indent, "(field ");
885    dump_insn_field(bits->field, indent+1);
886    dumpf(indent, " )\n");
887    dumpf(indent, "(last ");
888    dump_insn_bits(bits->last, indent+1, levels-1);
889  }
890}
891
892
893
894static void
895dump_insn(insn *entry, int indent, int levels)
896{
897  printf("(insn*)%p\n", entry);
898
899  if (levels && entry != NULL) {
900
901    dumpf(indent, "(file_entry ");
902    dump_table_entry(entry->file_entry, indent+1);
903    dumpf(indent, " )\n");
904
905    dumpf(indent, "(fields ");
906    dump_insn_fields(entry->fields, indent+1);
907    dumpf(indent, " )\n");
908
909    dumpf(indent, "(next ");
910    dump_insn(entry->next, indent+1, levels-1);
911    dumpf(indent, " )\n");
912
913  }
914
915}
916
917
918static void
919dump_insn_table(insn_table *table,
920		int indent, int levels)
921{
922
923  printf("(insn_table*)%p\n", table);
924
925  if (levels && table != NULL) {
926
927    dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr);
928
929    dumpf(indent, "(expanded_bits ");
930    dump_insn_bits(table->expanded_bits, indent+1, -1);
931    dumpf(indent, " )\n");
932
933    dumpf(indent, "(int nr_insn %d)\n", table->nr_insn);
934
935    dumpf(indent, "(insns ");
936    dump_insn(table->insns, indent+1, table->nr_insn);
937    dumpf(indent, " )\n");
938
939    dumpf(indent, "(opcode_rule ");
940    dump_decode_rule(table->opcode_rule, indent+1);
941    dumpf(indent, " )\n");
942
943    dumpf(indent, "(opcode ");
944    dump_opcode_field(table->opcode, indent+1, 1);
945    dumpf(indent, " )\n");
946
947    dumpf(indent, "(nr_entries %d)\n", table->entries);
948    dumpf(indent, "(entries ");
949    dump_insn_table(table->entries, indent+1, table->nr_entries);
950    dumpf(indent, " )\n");
951
952    dumpf(indent, "(sibling ", table->sibling);
953    dump_insn_table(table->sibling, indent+1, levels-1);
954    dumpf(indent, " )\n");
955
956    dumpf(indent, "(parent ", table->parent);
957    dump_insn_table(table->parent, indent+1, 0);
958    dumpf(indent, " )\n");
959
960  }
961}
962
963int insn_bit_size = max_insn_bit_size;
964int hi_bit_nr;
965int generate_expanded_instructions;
966
967int
968main(int argc, char **argv)
969{
970  filter *filters = NULL;
971  decode_table *decode_rules = NULL;
972  insn_table *instructions = NULL;
973  cache_table *cache_rules = NULL;
974
975  if (argc != 5)
976    error("Usage: insn <filter> <hi-bit-nr> <decode-table> <insn-table>\n");
977
978  filters = new_filter(argv[1], filters);
979  hi_bit_nr = a2i(argv[2]);
980  ASSERT(hi_bit_nr < insn_bit_size);
981  decode_rules = load_decode_table(argv[3], hi_bit_nr);
982  instructions = load_insn_table(argv[4], decode_rules, filters, NULL,
983				 &cache_rules);
984  insn_table_expand_insns(instructions);
985
986  dump_insn_table(instructions, 0, -1);
987  return 0;
988}
989
990#endif
991