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