1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2 
3    Copyright 2002-2013 Free Software Foundation, Inc.
4 
5    Contributed by Andrew Cagney.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 
23 #include "misc.h"
24 #include "lf.h"
25 #include "table.h"
26 #include "filter.h"
27 #include "igen.h"
28 #include "ld-insn.h"
29 
30 static insn_word_entry *
parse_insn_word(line_ref * line,char * string,int word_nr)31 parse_insn_word (line_ref *line, char *string, int word_nr)
32 {
33   char *chp;
34   insn_word_entry *word = ZALLOC (insn_word_entry);
35 
36   /* create a leading sentinal */
37   word->first = ZALLOC (insn_field_entry);
38   word->first->first = -1;
39   word->first->last = -1;
40   word->first->width = 0;
41 
42   /* and a trailing sentinal */
43   word->last = ZALLOC (insn_field_entry);
44   word->last->first = options.insn_bit_size;
45   word->last->last = options.insn_bit_size;
46   word->last->width = 0;
47 
48   /* link them together */
49   word->first->next = word->last;
50   word->last->prev = word->first;
51 
52   /* now work through the formats */
53   chp = skip_spaces (string);
54 
55   while (*chp != '\0')
56     {
57       char *start_pos;
58       int strlen_pos;
59       char *start_val;
60       int strlen_val;
61       insn_field_entry *new_field;
62 
63       /* create / link in the new field */
64       new_field = ZALLOC (insn_field_entry);
65       new_field->next = word->last;
66       new_field->prev = word->last->prev;
67       new_field->next->prev = new_field;
68       new_field->prev->next = new_field;
69       new_field->word_nr = word_nr;
70 
71       /* break out the first field (if present) */
72       start_pos = chp;
73       chp = skip_to_separator (chp, ".,!");
74       strlen_pos = back_spaces (start_pos, chp) - start_pos;
75 
76       /* break out the second field (if present) */
77       if (*chp != '.')
78 	{
79 	  /* assume what was specified was the value (and not the start
80 	     position).  Assume the value length implicitly specifies
81 	     the number of bits */
82 	  start_val = start_pos;
83 	  strlen_val = strlen_pos;
84 	  start_pos = "";
85 	  strlen_pos = 0;
86 	}
87       else
88 	{
89 	  chp++;		/* skip `.' */
90 	  chp = skip_spaces (chp);
91 	  start_val = chp;
92 	  if (*chp == '/' || *chp == '*')
93 	    {
94 	      do
95 		{
96 		  chp++;
97 		}
98 	      while (*chp == '/' || *chp == '*');
99 	    }
100 	  else if (isalpha (*start_val))
101 	    {
102 	      do
103 		{
104 		  chp++;
105 		}
106 	      while (isalnum (*chp) || *chp == '_');
107 	    }
108 	  else if (isdigit (*start_val))
109 	    {
110 	      do
111 		{
112 		  chp++;
113 		}
114 	      while (isalnum (*chp));
115 	    }
116 	  strlen_val = chp - start_val;
117 	  chp = skip_spaces (chp);
118 	}
119       if (strlen_val == 0)
120 	error (line, "Empty value field\n");
121 
122       /* break out any conditional fields - { [ "!" | "=" [ <value> | <field-name> } */
123       while (*chp == '!' || *chp == '=')
124 	{
125 	  char *start;
126 	  char *end;
127 	  int len;
128 	  insn_field_cond *new_cond = ZALLOC (insn_field_cond);
129 
130 	  /* determine the conditional test */
131 	  switch (*chp)
132 	    {
133 	    case '=':
134 	      new_cond->test = insn_field_cond_eq;
135 	      break;
136 	    case '!':
137 	      new_cond->test = insn_field_cond_ne;
138 	      break;
139 	    default:
140 	      ASSERT (0);
141 	    }
142 
143 	  /* save the value */
144 	  chp++;
145 	  chp = skip_spaces (chp);
146 	  start = chp;
147 	  chp = skip_to_separator (chp, "+,:!=");
148 	  end = back_spaces (start, chp);
149 	  len = end - start;
150 	  if (len == 0)
151 	    error (line, "Missing or invalid conditional value\n");
152 	  new_cond->string = NZALLOC (char, len + 1);
153 	  strncpy (new_cond->string, start, len);
154 
155 	  /* determine the conditional type */
156 	  if (isdigit (*start))
157 	    {
158 	      /* [ "!" | "=" ] <value> */
159 	      new_cond->type = insn_field_cond_value;
160 	      new_cond->value = a2i (new_cond->string);
161 	    }
162 	  else
163 	    {
164 	      /* [ "!" | "=" ] <field>  - check field valid */
165 	      new_cond->type = insn_field_cond_field;
166 	      /* new_cond->field is determined in later */
167 	    }
168 
169 	  /* Only a single `=' is permitted. */
170 	  if ((new_cond->test == insn_field_cond_eq
171 	       && new_field->conditions != NULL)
172 	      || (new_field->conditions != NULL
173 		  && new_field->conditions->test == insn_field_cond_eq))
174 	    error (line, "Only single conditional when `=' allowed\n");
175 
176 	  /* insert it */
177 	  {
178 	    insn_field_cond **last = &new_field->conditions;
179 	    while (*last != NULL)
180 	      last = &(*last)->next;
181 	    *last = new_cond;
182 	  }
183 	}
184 
185       /* NOW verify that the field was finished */
186       if (*chp == ',')
187 	{
188 	  chp = skip_spaces (chp + 1);
189 	  if (*chp == '\0')
190 	    error (line, "empty field\n");
191 	}
192       else if (*chp != '\0')
193 	{
194 	  error (line, "Missing field separator\n");
195 	}
196 
197       /* copy the value */
198       new_field->val_string = NZALLOC (char, strlen_val + 1);
199       strncpy (new_field->val_string, start_val, strlen_val);
200       if (isdigit (new_field->val_string[0]))
201 	{
202 	  if (strlen_pos == 0)
203 	    {
204 	      /* when the length/pos field is omited, an integer field
205 	         is always binary */
206 	      unsigned64 val = 0;
207 	      int i;
208 	      for (i = 0; i < strlen_val; i++)
209 		{
210 		  if (new_field->val_string[i] != '0'
211 		      && new_field->val_string[i] != '1')
212 		    error (line, "invalid binary field %s\n",
213 			   new_field->val_string);
214 		  val = (val << 1) + (new_field->val_string[i] == '1');
215 		}
216 	      new_field->val_int = val;
217 	      new_field->type = insn_field_int;
218 	    }
219 	  else
220 	    {
221 	      new_field->val_int = a2i (new_field->val_string);
222 	      new_field->type = insn_field_int;
223 	    }
224 	}
225       else if (new_field->val_string[0] == '/')
226 	{
227 	  new_field->type = insn_field_reserved;
228 	}
229       else if (new_field->val_string[0] == '*')
230 	{
231 	  new_field->type = insn_field_wild;
232 	}
233       else
234 	{
235 	  new_field->type = insn_field_string;
236 	  if (filter_is_member (word->field_names, new_field->val_string))
237 	    error (line, "Field name %s is duplicated\n",
238 		   new_field->val_string);
239 	  filter_parse (&word->field_names, new_field->val_string);
240 	}
241       if (new_field->type != insn_field_string
242 	  && new_field->conditions != NULL)
243 	error (line, "Conditionals can only be applied to named fields\n");
244 
245       /* the copy the position */
246       new_field->pos_string = NZALLOC (char, strlen_pos + 1);
247       strncpy (new_field->pos_string, start_pos, strlen_pos);
248       if (strlen_pos == 0)
249 	{
250 	  new_field->first = new_field->prev->last + 1;
251 	  if (new_field->first == 0	/* first field */
252 	      && *chp == '\0'	/* no further fields */
253 	      && new_field->type == insn_field_string)
254 	    {
255 	      /* A single string without any position, assume that it
256 	         represents the entire instruction word */
257 	      new_field->width = options.insn_bit_size;
258 	    }
259 	  else
260 	    {
261 	      /* No explicit width/position, assume value implicitly
262 	         supplies the width */
263 	      new_field->width = strlen_val;
264 	    }
265 	  new_field->last = new_field->first + new_field->width - 1;
266 	  if (new_field->last >= options.insn_bit_size)
267 	    error (line, "Bit position %d exceed instruction bit size (%d)\n",
268 		   new_field->last, options.insn_bit_size);
269 	}
270       else if (options.insn_specifying_widths)
271 	{
272 	  new_field->first = new_field->prev->last + 1;
273 	  new_field->width = a2i (new_field->pos_string);
274 	  new_field->last = new_field->first + new_field->width - 1;
275 	  if (new_field->last >= options.insn_bit_size)
276 	    error (line, "Bit position %d exceed instruction bit size (%d)\n",
277 		   new_field->last, options.insn_bit_size);
278 	}
279       else
280 	{
281 	  new_field->first = target_a2i (options.hi_bit_nr,
282 					 new_field->pos_string);
283 	  new_field->last = new_field->next->first - 1;	/* guess */
284 	  new_field->width = new_field->last - new_field->first + 1;	/* guess */
285 	  new_field->prev->last = new_field->first - 1;	/*fix */
286 	  new_field->prev->width = new_field->first - new_field->prev->first;	/*fix */
287 	}
288     }
289 
290   /* fiddle first/last so that the sentinals disapear */
291   ASSERT (word->first->last < 0);
292   ASSERT (word->last->first >= options.insn_bit_size);
293   word->first = word->first->next;
294   word->last = word->last->prev;
295 
296   /* check that the last field goes all the way to the last bit */
297   if (word->last->last != options.insn_bit_size - 1)
298     {
299       if (options.warn.width)
300 	options.warning (line, "Instruction format is not %d bits wide\n",
301 			 options.insn_bit_size);
302       word->last->last = options.insn_bit_size - 1;
303     }
304 
305   /* now go over this again, pointing each bit position at a field
306      record */
307   {
308     insn_field_entry *field;
309     for (field = word->first;
310 	 field->last < options.insn_bit_size; field = field->next)
311       {
312 	int i;
313 	for (i = field->first; i <= field->last; i++)
314 	  {
315 	    word->bit[i] = ZALLOC (insn_bit_entry);
316 	    word->bit[i]->field = field;
317 	    switch (field->type)
318 	      {
319 	      case insn_field_invalid:
320 		ASSERT (0);
321 		break;
322 	      case insn_field_int:
323 		word->bit[i]->mask = 1;
324 		word->bit[i]->value = ((field->val_int
325 					& ((insn_uint) 1 <<
326 					   (field->last - i))) != 0);
327 	      case insn_field_reserved:
328 	      case insn_field_wild:
329 	      case insn_field_string:
330 		/* if we encounter a constant conditional, encode
331 		   their bit value. */
332 		if (field->conditions != NULL
333 		    && field->conditions->test == insn_field_cond_eq
334 		    && field->conditions->type == insn_field_cond_value)
335 		  {
336 		    word->bit[i]->mask = 1;
337 		    word->bit[i]->value = ((field->conditions->value
338 					    & ((insn_uint) 1 <<
339 					       (field->last - i))) != 0);
340 		  }
341 		break;
342 	      }
343 	  }
344       }
345   }
346 
347   return word;
348 }
349 
350 
351 static void
parse_insn_words(insn_entry * insn,char * formats)352 parse_insn_words (insn_entry * insn, char *formats)
353 {
354   insn_word_entry **last_word = &insn->words;
355   char *chp;
356 
357   /* now work through the formats */
358   insn->nr_words = 0;
359   chp = formats;
360 
361   while (1)
362     {
363       char *start_pos;
364       char *end_pos;
365       int strlen_pos;
366       char *format;
367       insn_word_entry *new_word;
368 
369       /* skip leading spaces */
370       chp = skip_spaces (chp);
371 
372       /* break out the format */
373       start_pos = chp;
374       chp = skip_to_separator (chp, "+");
375       end_pos = back_spaces (start_pos, chp);
376       strlen_pos = end_pos - start_pos;
377 
378       /* check that something was there */
379       if (strlen_pos == 0)
380 	error (insn->line, "missing or empty instruction format\n");
381 
382       /* parse the field */
383       format = NZALLOC (char, strlen_pos + 1);
384       strncpy (format, start_pos, strlen_pos);
385       new_word = parse_insn_word (insn->line, format, insn->nr_words);
386       insn->nr_words++;
387       if (filter_is_common (insn->field_names, new_word->field_names))
388 	error (insn->line, "Field name duplicated between two words\n");
389       filter_add (&insn->field_names, new_word->field_names);
390 
391       /* insert it */
392       *last_word = new_word;
393       last_word = &new_word->next;
394 
395       /* last format? */
396       if (*chp == '\0')
397 	break;
398       ASSERT (*chp == '+');
399       chp++;
400     }
401 
402   /* create a quick access array (indexed by word) of the same structure */
403   {
404     int i;
405     insn_word_entry *word;
406     insn->word = NZALLOC (insn_word_entry *, insn->nr_words + 1);
407     for (i = 0, word = insn->words;
408 	 i < insn->nr_words; i++, word = word->next)
409       insn->word[i] = word;
410   }
411 
412   /* Go over all fields that have conditionals refering to other
413      fields.  Link the fields up.  Verify that the two fields have the
414      same size. Verify that the two fields are different */
415   {
416     int i;
417     for (i = 0; i < insn->nr_words; i++)
418       {
419 	insn_word_entry *word = insn->word[i];
420 	insn_field_entry *f;
421 	for (f = word->first; f->last < options.insn_bit_size; f = f->next)
422 	  {
423 	    insn_field_cond *cond;
424 	    for (cond = f->conditions; cond != NULL; cond = cond->next)
425 	      {
426 		if (cond->type == insn_field_cond_field)
427 		  {
428 		    int j;
429 		    if (strcmp (cond->string, f->val_string) == 0)
430 		      error (insn->line,
431 			     "Conditional `%s' of field `%s' refers to its self\n",
432 			     cond->string, f->val_string);
433 		    for (j = 0; j <= i && cond->field == NULL; j++)
434 		      {
435 			insn_word_entry *refered_word = insn->word[j];
436 			insn_field_entry *refered_field;
437 			for (refered_field = refered_word->first;
438 			     refered_field != NULL && cond->field == NULL;
439 			     refered_field = refered_field->next)
440 			  {
441 			    if (refered_field->type == insn_field_string
442 				&& strcmp (refered_field->val_string,
443 					   cond->string) == 0)
444 			      {
445 				/* found field being refered to by conditonal */
446 				cond->field = refered_field;
447 				/* check refered to and this field are
448 				   the same size */
449 				if (f->width != refered_field->width)
450 				  error (insn->line,
451 					 "Conditional `%s' of field `%s' should be of size %s\n",
452 					 cond->string, f->val_string,
453 					 refered_field->width);
454 			      }
455 			  }
456 		      }
457 		    if (cond->field == NULL)
458 		      error (insn->line,
459 			     "Conditional `%s' of field `%s' not yet defined\n",
460 			     cond->string, f->val_string);
461 		  }
462 	      }
463 	  }
464       }
465   }
466 
467 }
468 
469 typedef enum
470 {
471   unknown_record = 0,
472   insn_record,			/* default */
473   code_record,
474   cache_record,
475   compute_record,
476   scratch_record,
477   option_record,
478   string_function_record,
479   function_record,
480   internal_record,
481   define_record,
482   include_record,
483   model_processor_record,
484   model_macro_record,
485   model_data_record,
486   model_static_record,
487   model_function_record,
488   model_internal_record,
489 }
490 insn_record_type;
491 
492 static const name_map insn_type_map[] = {
493   {"option", option_record},
494   {"cache", cache_record},
495   {"compute", compute_record},
496   {"scratch", scratch_record},
497   {"define", define_record},
498   {"include", include_record},
499   {"%s", string_function_record},
500   {"function", function_record},
501   {"internal", internal_record},
502   {"model", model_processor_record},
503   {"model-macro", model_macro_record},
504   {"model-data", model_data_record},
505   {"model-static", model_static_record},
506   {"model-internal", model_internal_record},
507   {"model-function", model_function_record},
508   {NULL, insn_record},
509 };
510 
511 
512 static int
record_is_old(table_entry * entry)513 record_is_old (table_entry *entry)
514 {
515   if (entry->nr_fields > record_type_field
516       && strlen (entry->field[record_type_field]) == 0)
517     return 1;
518   return 0;
519 }
520 
521 static insn_record_type
record_type(table_entry * entry)522 record_type (table_entry *entry)
523 {
524   switch (entry->type)
525     {
526     case table_code_entry:
527       return code_record;
528 
529     case table_colon_entry:
530       if (record_is_old (entry))
531 	{
532 	  /* old-format? */
533 	  if (entry->nr_fields > old_record_type_field)
534 	    {
535 	      int i = name2i (entry->field[old_record_type_field],
536 			      insn_type_map);
537 	      return i;
538 	    }
539 	  else
540 	    {
541 	      return unknown_record;
542 	    }
543 	}
544       else if (entry->nr_fields > record_type_field
545 	       && entry->field[0][0] == '\0')
546 	{
547 	  /* new-format? */
548 	  int i = name2i (entry->field[record_type_field],
549 			  insn_type_map);
550 	  return i;
551 	}
552       else
553 	return insn_record;	/* default */
554     }
555   return unknown_record;
556 }
557 
558 static int
record_prefix_is(table_entry * entry,char ch,int nr_fields)559 record_prefix_is (table_entry *entry, char ch, int nr_fields)
560 {
561   if (entry->type != table_colon_entry)
562     return 0;
563   if (entry->nr_fields < nr_fields)
564     return 0;
565   if (entry->field[0][0] != ch && ch != '\0')
566     return 0;
567   return 1;
568 }
569 
570 static table_entry *
parse_model_data_record(insn_table * isa,table * file,table_entry * record,int nr_fields,model_data ** list)571 parse_model_data_record (insn_table *isa,
572 			 table *file,
573 			 table_entry *record,
574 			 int nr_fields, model_data **list)
575 {
576   table_entry *model_record = record;
577   table_entry *code_record = NULL;
578   model_data *new_data;
579   if (record->nr_fields < nr_fields)
580     error (record->line, "Incorrect number of fields\n");
581   record = table_read (file);
582   if (record->type == table_code_entry)
583     {
584       code_record = record;
585       record = table_read (file);
586     }
587   /* create the new data record */
588   new_data = ZALLOC (model_data);
589   new_data->line = model_record->line;
590   filter_parse (&new_data->flags,
591 		model_record->field[record_filter_flags_field]);
592   new_data->entry = model_record;
593   new_data->code = code_record;
594   /* append it if not filtered out */
595   if (!is_filtered_out (options.flags_filter,
596 			model_record->field[record_filter_flags_field])
597       && !is_filtered_out (options.model_filter,
598 			   model_record->field[record_filter_models_field]))
599     {
600       while (*list != NULL)
601 	list = &(*list)->next;
602       *list = new_data;
603     }
604   return record;
605 }
606 
607 
608 typedef enum
609 {
610   insn_bit_size_option = 1,
611   insn_specifying_widths_option,
612   hi_bit_nr_option,
613   flags_filter_option,
614   model_filter_option,
615   multi_sim_option,
616   format_names_option,
617   gen_delayed_branch,
618   unknown_option,
619 }
620 option_names;
621 
622 static const name_map option_map[] = {
623   {"insn-bit-size", insn_bit_size_option},
624   {"insn-specifying-widths", insn_specifying_widths_option},
625   {"hi-bit-nr", hi_bit_nr_option},
626   {"flags-filter", flags_filter_option},
627   {"model-filter", model_filter_option},
628   {"multi-sim", multi_sim_option},
629   {"format-names", format_names_option},
630   {"gen-delayed-branch", gen_delayed_branch},
631   {NULL, unknown_option},
632 };
633 
634 static table_entry *
parse_include_record(table * file,table_entry * record)635 parse_include_record (table *file, table_entry *record)
636 {
637   /* parse the include record */
638   if (record->nr_fields < nr_include_fields)
639     error (record->line, "Incorrect nr fields for include record\n");
640   /* process it */
641   if (!is_filtered_out (options.flags_filter,
642 			record->field[record_filter_flags_field])
643       && !is_filtered_out (options.model_filter,
644 			   record->field[record_filter_models_field]))
645     {
646       table_push (file, record->line, options.include,
647 		  record->field[include_filename_field]);
648     }
649   /* nb: can't read next record until after the file has been pushed */
650   record = table_read (file);
651   return record;
652 }
653 
654 
655 static table_entry *
parse_option_record(table * file,table_entry * record)656 parse_option_record (table *file, table_entry *record)
657 {
658   table_entry *option_record;
659   /* parse the option record */
660   option_record = record;
661   if (record->nr_fields < nr_option_fields)
662     error (record->line, "Incorrect nr of fields for option record\n");
663   record = table_read (file);
664   /* process it */
665   if (!is_filtered_out (options.flags_filter,
666 			option_record->field[record_filter_flags_field])
667       && !is_filtered_out (options.model_filter,
668 			   option_record->field[record_filter_models_field]))
669     {
670       char *name = option_record->field[option_name_field];
671       option_names option = name2i (name, option_map);
672       char *value = option_record->field[option_value_field];
673       switch (option)
674 	{
675 	case insn_bit_size_option:
676 	  {
677 	    options.insn_bit_size = a2i (value);
678 	    if (options.insn_bit_size < 0
679 		|| options.insn_bit_size > max_insn_bit_size)
680 	      error (option_record->line,
681 		     "Instruction bit size out of range\n");
682 	    if (options.hi_bit_nr != options.insn_bit_size - 1
683 		&& options.hi_bit_nr != 0)
684 	      error (option_record->line,
685 		     "insn-bit-size / hi-bit-nr conflict\n");
686 	    break;
687 	  }
688 	case insn_specifying_widths_option:
689 	  {
690 	    options.insn_specifying_widths = a2i (value);
691 	    break;
692 	  }
693 	case hi_bit_nr_option:
694 	  {
695 	    options.hi_bit_nr = a2i (value);
696 	    if (options.hi_bit_nr != 0
697 		&& options.hi_bit_nr != options.insn_bit_size - 1)
698 	      error (option_record->line,
699 		     "hi-bit-nr / insn-bit-size conflict\n");
700 	    break;
701 	  }
702 	case flags_filter_option:
703 	  {
704 	    filter_parse (&options.flags_filter, value);
705 	    break;
706 	  }
707 	case model_filter_option:
708 	  {
709 	    filter_parse (&options.model_filter, value);
710 	    break;
711 	  }
712 	case multi_sim_option:
713 	  {
714 	    options.gen.multi_sim = a2i (value);
715 	    break;
716 	  }
717 	case format_names_option:
718 	  {
719 	    filter_parse (&options.format_name_filter, value);
720 	    break;
721 	  }
722 	case gen_delayed_branch:
723 	  {
724 	    options.gen.delayed_branch = a2i (value);
725 	    break;
726 	  }
727 	case unknown_option:
728 	  {
729 	    error (option_record->line, "Unknown option - %s\n", name);
730 	    break;
731 	  }
732 	}
733     }
734   return record;
735 }
736 
737 
738 static table_entry *
parse_function_record(table * file,table_entry * record,function_entry ** list,function_entry ** list_entry,int is_internal,model_table * model)739 parse_function_record (table *file,
740 		       table_entry *record,
741 		       function_entry ** list,
742 		       function_entry ** list_entry,
743 		       int is_internal, model_table *model)
744 {
745   function_entry *new_function;
746   new_function = ZALLOC (function_entry);
747   new_function->line = record->line;
748   new_function->is_internal = is_internal;
749   /* parse the function header */
750   if (record_is_old (record))
751     {
752       if (record->nr_fields < nr_old_function_fields)
753 	error (record->line, "Missing fields from (old) function record\n");
754       new_function->type = record->field[old_function_typedef_field];
755       new_function->type = record->field[old_function_typedef_field];
756       if (record->nr_fields > old_function_param_field)
757 	new_function->param = record->field[old_function_param_field];
758       new_function->name = record->field[old_function_name_field];
759     }
760   else
761     {
762       if (record->nr_fields < nr_function_fields)
763 	error (record->line, "Missing fields from function record\n");
764       filter_parse (&new_function->flags,
765 		    record->field[record_filter_flags_field]);
766       filter_parse (&new_function->models,
767 		    record->field[record_filter_models_field]);
768       new_function->type = record->field[function_typedef_field];
769       new_function->param = record->field[function_param_field];
770       new_function->name = record->field[function_name_field];
771     }
772   record = table_read (file);
773   /* parse any function-model records */
774   while (record != NULL
775 	 && record_prefix_is (record, '*', nr_function_model_fields))
776     {
777       char *model_name = record->field[function_model_name_field] + 1;	/*skip `*' */
778       filter_parse (&new_function->models, model_name);
779       if (!filter_is_subset (model->processors, new_function->models))
780 	{
781 	  error (record->line, "machine model `%s' undefined\n", model_name);
782 	}
783       record = table_read (file);
784     }
785   /* parse the function body */
786   if (record->type == table_code_entry)
787     {
788       new_function->code = record;
789       record = table_read (file);
790     }
791   /* insert it */
792   if (!filter_is_subset (options.flags_filter, new_function->flags))
793     {
794       if (options.warn.discard)
795 	notify (new_function->line, "Discarding function %s - filter flags\n",
796 		new_function->name);
797     }
798   else if (new_function->models != NULL
799 	   && !filter_is_common (options.model_filter, new_function->models))
800     {
801       if (options.warn.discard)
802 	notify (new_function->line,
803 		"Discarding function %s - filter models\n",
804 		new_function->name);
805     }
806   else
807     {
808       while (*list != NULL)
809 	list = &(*list)->next;
810       *list = new_function;
811       if (list_entry != NULL)
812 	*list_entry = new_function;
813     }
814   /* done */
815   return record;
816 }
817 
818 static void
parse_insn_model_record(table * file,table_entry * record,insn_entry * insn,model_table * model)819 parse_insn_model_record (table *file,
820 			 table_entry *record,
821 			 insn_entry * insn, model_table *model)
822 {
823   insn_model_entry **last_insn_model;
824   insn_model_entry *new_insn_model = ZALLOC (insn_model_entry);
825   /* parse it */
826   new_insn_model->line = record->line;
827   if (record->nr_fields > insn_model_unit_data_field)
828     new_insn_model->unit_data = record->field[insn_model_unit_data_field];
829   new_insn_model->insn = insn;
830   /* parse the model names, verify that all were defined */
831   new_insn_model->names = NULL;
832   filter_parse (&new_insn_model->names,
833 		record->field[insn_model_name_field] + 1 /*skip `*' */ );
834   if (new_insn_model->names == NULL)
835     {
836       /* No processor names - a generic model entry, enter it into all
837          the non-empty fields */
838       int index;
839       for (index = 0; index < model->nr_models; index++)
840 	if (insn->model[index] == 0)
841 	  {
842 	    insn->model[index] = new_insn_model;
843 	  }
844       /* also add the complete processor set to this processor's set */
845       filter_add (&insn->processors, model->processors);
846     }
847   else
848     {
849       /* Find the corresponding master model record for each name so
850          that they can be linked in. */
851       int index;
852       char *name = "";
853       while (1)
854 	{
855 	  name = filter_next (new_insn_model->names, name);
856 	  if (name == NULL)
857 	    break;
858 	  index = filter_is_member (model->processors, name) - 1;
859 	  if (index < 0)
860 	    {
861 	      error (new_insn_model->line,
862 		     "machine model `%s' undefined\n", name);
863 	    }
864 	  /* store it in the corresponding model array entry */
865 	  if (insn->model[index] != NULL && insn->model[index]->names != NULL)
866 	    {
867 	      warning (new_insn_model->line,
868 		       "machine model `%s' previously defined\n", name);
869 	      error (insn->model[index]->line, "earlier definition\n");
870 	    }
871 	  insn->model[index] = new_insn_model;
872 	  /* also add the name to the instructions processor set as an
873 	     alternative lookup mechanism */
874 	  filter_parse (&insn->processors, name);
875 	}
876     }
877   /* link it in */
878   last_insn_model = &insn->models;
879   while ((*last_insn_model) != NULL)
880     last_insn_model = &(*last_insn_model)->next;
881   *last_insn_model = new_insn_model;
882 }
883 
884 
885 static void
parse_insn_mnemonic_record(table * file,table_entry * record,insn_entry * insn)886 parse_insn_mnemonic_record (table *file,
887 			    table_entry *record, insn_entry * insn)
888 {
889   insn_mnemonic_entry **last_insn_mnemonic;
890   insn_mnemonic_entry *new_insn_mnemonic = ZALLOC (insn_mnemonic_entry);
891   /* parse it */
892   new_insn_mnemonic->line = record->line;
893   ASSERT (record->nr_fields > insn_mnemonic_format_field);
894   new_insn_mnemonic->format = record->field[insn_mnemonic_format_field];
895   ASSERT (new_insn_mnemonic->format[0] == '"');
896   if (new_insn_mnemonic->format[strlen (new_insn_mnemonic->format) - 1] !=
897       '"')
898     error (new_insn_mnemonic->line,
899 	   "Missing closing double quote in mnemonic field\n");
900   if (record->nr_fields > insn_mnemonic_condition_field)
901     new_insn_mnemonic->condition =
902       record->field[insn_mnemonic_condition_field];
903   new_insn_mnemonic->insn = insn;
904   /* insert it */
905   last_insn_mnemonic = &insn->mnemonics;
906   while ((*last_insn_mnemonic) != NULL)
907     last_insn_mnemonic = &(*last_insn_mnemonic)->next;
908   insn->nr_mnemonics++;
909   *last_insn_mnemonic = new_insn_mnemonic;
910 }
911 
912 
913 static table_entry *
parse_macro_record(table * file,table_entry * record)914 parse_macro_record (table *file, table_entry *record)
915 {
916 #if 1
917   error (record->line, "Macros are not implemented");
918 #else
919   /* parse the define record */
920   if (record->nr_fields < nr_define_fields)
921     error (record->line, "Incorrect nr fields for define record\n");
922   /* process it */
923   if (!is_filtered_out (options.flags_filter,
924 			record->field[record_filter_flags_field])
925       && !is_filtered_out (options.model_filter,
926 			   record->field[record_filter_models_field]))
927     {
928       table_define (file,
929 		    record->line,
930 		    record->field[macro_name_field],
931 		    record->field[macro_args_field],
932 		    record->field[macro_expr_field]);
933     }
934   record = table_read (file);
935 #endif
936   return record;
937 }
938 
939 
940 insn_table *
load_insn_table(char * file_name,cache_entry * cache)941 load_insn_table (char *file_name, cache_entry *cache)
942 {
943   table *file = table_open (file_name);
944   table_entry *record = table_read (file);
945 
946   insn_table *isa = ZALLOC (insn_table);
947   model_table *model = ZALLOC (model_table);
948 
949   isa->model = model;
950   isa->caches = cache;
951 
952   while (record != NULL)
953     {
954 
955       switch (record_type (record))
956 	{
957 
958 	case include_record:
959 	  {
960 	    record = parse_include_record (file, record);
961 	    break;
962 	  }
963 
964 	case option_record:
965 	  {
966 	    if (isa->insns != NULL)
967 	      error (record->line, "Option after first instruction\n");
968 	    record = parse_option_record (file, record);
969 	    break;
970 	  }
971 
972 	case string_function_record:
973 	  {
974 	    function_entry *function = NULL;
975 	    record = parse_function_record (file, record,
976 					    &isa->functions,
977 					    &function, 0 /*is-internal */ ,
978 					    model);
979 	    /* convert a string function record into an internal function */
980 	    if (function != NULL)
981 	      {
982 		char *name = NZALLOC (char,
983 				      (strlen ("str_")
984 				       + strlen (function->name) + 1));
985 		strcat (name, "str_");
986 		strcat (name, function->name);
987 		function->name = name;
988 		function->type = "const char *";
989 	      }
990 	    break;
991 	  }
992 
993 	case function_record:	/* function record */
994 	  {
995 	    record = parse_function_record (file, record,
996 					    &isa->functions,
997 					    NULL, 0 /*is-internal */ ,
998 					    model);
999 	    break;
1000 	  }
1001 
1002 	case internal_record:
1003 	  {
1004 	    /* only insert it into the function list if it is unknown */
1005 	    function_entry *function = NULL;
1006 	    record = parse_function_record (file, record,
1007 					    &isa->functions,
1008 					    &function, 1 /*is-internal */ ,
1009 					    model);
1010 	    /* check what was inserted to see if a pseudo-instruction
1011 	       entry also needs to be created */
1012 	    if (function != NULL)
1013 	      {
1014 		insn_entry **insn = NULL;
1015 		if (strcmp (function->name, "illegal") == 0)
1016 		  {
1017 		    /* illegal function save it away */
1018 		    if (isa->illegal_insn != NULL)
1019 		      {
1020 			warning (function->line,
1021 				 "Multiple illegal instruction definitions\n");
1022 			error (isa->illegal_insn->line,
1023 			       "Location of first illegal instruction\n");
1024 		      }
1025 		    else
1026 		      insn = &isa->illegal_insn;
1027 		  }
1028 		if (insn != NULL)
1029 		  {
1030 		    *insn = ZALLOC (insn_entry);
1031 		    (*insn)->line = function->line;
1032 		    (*insn)->name = function->name;
1033 		    (*insn)->code = function->code;
1034 		  }
1035 	      }
1036 	    break;
1037 	  }
1038 
1039 	case scratch_record:	/* cache macro records */
1040 	case cache_record:
1041 	case compute_record:
1042 	  {
1043 	    cache_entry *new_cache;
1044 	    /* parse the cache record */
1045 	    if (record->nr_fields < nr_cache_fields)
1046 	      error (record->line,
1047 		     "Incorrect nr of fields for scratch/cache/compute record\n");
1048 	    /* create it */
1049 	    new_cache = ZALLOC (cache_entry);
1050 	    new_cache->line = record->line;
1051 	    filter_parse (&new_cache->flags,
1052 			  record->field[record_filter_flags_field]);
1053 	    filter_parse (&new_cache->models,
1054 			  record->field[record_filter_models_field]);
1055 	    new_cache->type = record->field[cache_typedef_field];
1056 	    new_cache->name = record->field[cache_name_field];
1057 	    filter_parse (&new_cache->original_fields,
1058 			  record->field[cache_original_fields_field]);
1059 	    new_cache->expression = record->field[cache_expression_field];
1060 	    /* insert it but only if not filtered out */
1061 	    if (!filter_is_subset (options.flags_filter, new_cache->flags))
1062 	      {
1063 		notify (new_cache->line,
1064 			"Discarding cache entry %s - filter flags\n",
1065 			new_cache->name);
1066 	      }
1067 	    else if (is_filtered_out (options.model_filter,
1068 				      record->
1069 				      field[record_filter_models_field]))
1070 	      {
1071 		notify (new_cache->line,
1072 			"Discarding cache entry %s - filter models\n",
1073 			new_cache->name);
1074 	      }
1075 	    else
1076 	      {
1077 		cache_entry **last;
1078 		last = &isa->caches;
1079 		while (*last != NULL)
1080 		  last = &(*last)->next;
1081 		*last = new_cache;
1082 	      }
1083 	    /* advance things */
1084 	    record = table_read (file);
1085 	    break;
1086 	  }
1087 
1088 	  /* model records */
1089 	case model_processor_record:
1090 	  {
1091 	    model_entry *new_model;
1092 	    /* parse the model */
1093 	    if (record->nr_fields < nr_model_processor_fields)
1094 	      error (record->line,
1095 		     "Incorrect nr of fields for model record\n");
1096 	    if (isa->insns != NULL)
1097 	      error (record->line, "Model appears after first instruction\n");
1098 	    new_model = ZALLOC (model_entry);
1099 	    filter_parse (&new_model->flags,
1100 			  record->field[record_filter_flags_field]);
1101 	    new_model->line = record->line;
1102 	    new_model->name = record->field[model_name_field];
1103 	    new_model->full_name = record->field[model_full_name_field];
1104 	    new_model->unit_data = record->field[model_unit_data_field];
1105 	    /* only insert it if not filtered out */
1106 	    if (!filter_is_subset (options.flags_filter, new_model->flags))
1107 	      {
1108 		notify (new_model->line,
1109 			"Discarding processor model %s - filter flags\n",
1110 			new_model->name);
1111 	      }
1112 	    else if (is_filtered_out (options.model_filter,
1113 				      record->
1114 				      field[record_filter_models_field]))
1115 	      {
1116 		notify (new_model->line,
1117 			"Discarding processor model %s - filter models\n",
1118 			new_model->name);
1119 	      }
1120 	    else if (filter_is_member (model->processors, new_model->name))
1121 	      {
1122 		error (new_model->line, "Duplicate processor model %s\n",
1123 		       new_model->name);
1124 	      }
1125 	    else
1126 	      {
1127 		model_entry **last;
1128 		last = &model->models;
1129 		while (*last != NULL)
1130 		  last = &(*last)->next;
1131 		*last = new_model;
1132 		/* count it */
1133 		model->nr_models++;
1134 		filter_parse (&model->processors, new_model->name);
1135 	      }
1136 	    /* advance things */
1137 	    record = table_read (file);
1138 	  }
1139 	  break;
1140 
1141 	case model_macro_record:
1142 	  record = parse_model_data_record (isa, file, record,
1143 					    nr_model_macro_fields,
1144 					    &model->macros);
1145 	  break;
1146 
1147 	case model_data_record:
1148 	  record = parse_model_data_record (isa, file, record,
1149 					    nr_model_data_fields,
1150 					    &model->data);
1151 	  break;
1152 
1153 	case model_static_record:
1154 	  record = parse_function_record (file, record,
1155 					  &model->statics,
1156 					  NULL, 0 /*is internal */ ,
1157 					  model);
1158 	  break;
1159 
1160 	case model_internal_record:
1161 	  record = parse_function_record (file, record,
1162 					  &model->internals,
1163 					  NULL, 1 /*is internal */ ,
1164 					  model);
1165 	  break;
1166 
1167 	case model_function_record:
1168 	  record = parse_function_record (file, record,
1169 					  &model->functions,
1170 					  NULL, 0 /*is internal */ ,
1171 					  model);
1172 	  break;
1173 
1174 	case insn_record:	/* instruction records */
1175 	  {
1176 	    insn_entry *new_insn;
1177 	    char *format;
1178 	    /* parse the instruction */
1179 	    if (record->nr_fields < nr_insn_fields)
1180 	      error (record->line,
1181 		     "Incorrect nr of fields for insn record\n");
1182 	    new_insn = ZALLOC (insn_entry);
1183 	    new_insn->line = record->line;
1184 	    filter_parse (&new_insn->flags,
1185 			  record->field[record_filter_flags_field]);
1186 	    /* save the format field.  Can't parse it until after the
1187 	       filter-out checks.  Could be filtered out because the
1188 	       format is invalid */
1189 	    format = record->field[insn_word_field];
1190 	    new_insn->format_name = record->field[insn_format_name_field];
1191 	    if (options.format_name_filter != NULL
1192 		&& !filter_is_member (options.format_name_filter,
1193 				      new_insn->format_name))
1194 	      error (new_insn->line,
1195 		     "Unreconized instruction format name `%s'\n",
1196 		     new_insn->format_name);
1197 	    filter_parse (&new_insn->options,
1198 			  record->field[insn_options_field]);
1199 	    new_insn->name = record->field[insn_name_field];
1200 	    record = table_read (file);
1201 	    /* Parse any model/assember records */
1202 	    new_insn->nr_models = model->nr_models;
1203 	    new_insn->model =
1204 	      NZALLOC (insn_model_entry *, model->nr_models + 1);
1205 	    while (record != NULL)
1206 	      {
1207 		if (record_prefix_is (record, '*', nr_insn_model_fields))
1208 		  parse_insn_model_record (file, record, new_insn, model);
1209 		else
1210 		  if (record_prefix_is (record, '"', nr_insn_mnemonic_fields))
1211 		  parse_insn_mnemonic_record (file, record, new_insn);
1212 		else
1213 		  break;
1214 		/* advance */
1215 		record = table_read (file);
1216 	      }
1217 	    /* Parse the code record */
1218 	    if (record != NULL && record->type == table_code_entry)
1219 	      {
1220 		new_insn->code = record;
1221 		record = table_read (file);
1222 	      }
1223 	    else if (options.warn.unimplemented)
1224 	      notify (new_insn->line, "unimplemented\n");
1225 	    /* insert it */
1226 	    if (!filter_is_subset (options.flags_filter, new_insn->flags))
1227 	      {
1228 		if (options.warn.discard)
1229 		  notify (new_insn->line,
1230 			  "Discarding instruction %s (flags-filter)\n",
1231 			  new_insn->name);
1232 	      }
1233 	    else if (new_insn->processors != NULL
1234 		     && options.model_filter != NULL
1235 		     && !filter_is_common (options.model_filter,
1236 					   new_insn->processors))
1237 	      {
1238 		/* only discard an instruction based in the processor
1239 		   model when both the instruction and the options are
1240 		   nonempty */
1241 		if (options.warn.discard)
1242 		  notify (new_insn->line,
1243 			  "Discarding instruction %s (processor-model)\n",
1244 			  new_insn->name);
1245 	      }
1246 	    else
1247 	      {
1248 		insn_entry **last;
1249 		/* finish the parsing */
1250 		parse_insn_words (new_insn, format);
1251 		/* append it */
1252 		last = &isa->insns;
1253 		while (*last)
1254 		  last = &(*last)->next;
1255 		*last = new_insn;
1256 		/* update global isa counters */
1257 		isa->nr_insns++;
1258 		if (isa->max_nr_words < new_insn->nr_words)
1259 		  isa->max_nr_words = new_insn->nr_words;
1260 		filter_add (&isa->flags, new_insn->flags);
1261 		filter_add (&isa->options, new_insn->options);
1262 	      }
1263 	    break;
1264 	  }
1265 
1266 	case define_record:
1267 	  record = parse_macro_record (file, record);
1268 	  break;
1269 
1270 	case unknown_record:
1271 	case code_record:
1272 	  error (record->line, "Unknown or unexpected entry\n");
1273 
1274 
1275 	}
1276     }
1277   return isa;
1278 }
1279 
1280 
1281 void
print_insn_words(lf * file,insn_entry * insn)1282 print_insn_words (lf *file, insn_entry * insn)
1283 {
1284   insn_word_entry *word = insn->words;
1285   if (word != NULL)
1286     {
1287       while (1)
1288 	{
1289 	  insn_field_entry *field = word->first;
1290 	  while (1)
1291 	    {
1292 	      insn_field_cond *cond;
1293 
1294 	      if (options.insn_specifying_widths)
1295 		lf_printf (file, "%d.", field->width);
1296 	      else
1297 		lf_printf (file, "%d.",
1298 			   i2target (options.hi_bit_nr, field->first));
1299 	      switch (field->type)
1300 		{
1301 		case insn_field_invalid:
1302 		  ASSERT (0);
1303 		  break;
1304 		case insn_field_int:
1305 		  lf_printf (file, "0x%lx", (long) field->val_int);
1306 		  break;
1307 		case insn_field_reserved:
1308 		  lf_printf (file, "/");
1309 		  break;
1310 		case insn_field_wild:
1311 		  lf_printf (file, "*");
1312 		  break;
1313 		case insn_field_string:
1314 		  lf_printf (file, "%s", field->val_string);
1315 
1316 		  if (field->conditions == NULL)
1317 		    break;
1318 
1319 		  if (field->conditions->test == insn_field_cond_eq)
1320 		    {
1321 		      if (field->conditions->type == insn_field_cond_value)
1322 			lf_printf (file, "=%ld",
1323 				   (long) field->conditions->value);
1324 		      else
1325 			lf_printf (file, "=%s", field->conditions->string);
1326 
1327 		      /* There can be only one equality condition.  */
1328 		      ASSERT (field->conditions->next == NULL);
1329 		      break;
1330 		    }
1331 
1332 		  for (cond = field->conditions;
1333 		       cond != NULL;
1334 		       cond = cond->next)
1335 		    {
1336 		      ASSERT (cond->test == insn_field_cond_ne);
1337 
1338 		      if (cond->type == insn_field_cond_value)
1339 			lf_printf (file, "!%ld", (long) cond->value);
1340 		      else
1341 			lf_printf (file, "!%s", cond->string);
1342 		    }
1343 		  break;
1344 		}
1345 	      if (field == word->last)
1346 		break;
1347 	      field = field->next;
1348 	      lf_printf (file, ",");
1349 	    }
1350 	  word = word->next;
1351 	  if (word == NULL)
1352 	    break;
1353 	  lf_printf (file, "+");
1354 	}
1355     }
1356 }
1357 
1358 
1359 
1360 void
function_entry_traverse(lf * file,function_entry * functions,function_entry_handler * handler,void * data)1361 function_entry_traverse (lf *file,
1362 			 function_entry * functions,
1363 			 function_entry_handler * handler, void *data)
1364 {
1365   function_entry *function;
1366   for (function = functions; function != NULL; function = function->next)
1367     {
1368       handler (file, function, data);
1369     }
1370 }
1371 
1372 void
insn_table_traverse_insn(lf * file,insn_table * isa,insn_entry_handler * handler,void * data)1373 insn_table_traverse_insn (lf *file,
1374 			  insn_table *isa,
1375 			  insn_entry_handler * handler, void *data)
1376 {
1377   insn_entry *insn;
1378   for (insn = isa->insns; insn != NULL; insn = insn->next)
1379     {
1380       handler (file, isa, insn, data);
1381     }
1382 }
1383 
1384 
1385 static void
dump_function_entry(lf * file,char * prefix,function_entry * entry,char * suffix)1386 dump_function_entry (lf *file,
1387 		     char *prefix, function_entry * entry, char *suffix)
1388 {
1389   lf_printf (file, "%s(function_entry *) 0x%lx", prefix, (long) entry);
1390   if (entry != NULL)
1391     {
1392       dump_line_ref (file, "\n(line ", entry->line, ")");
1393       dump_filter (file, "\n(flags ", entry->flags, ")");
1394       lf_printf (file, "\n(type \"%s\")", entry->type);
1395       lf_printf (file, "\n(name \"%s\")", entry->name);
1396       lf_printf (file, "\n(param \"%s\")", entry->param);
1397       dump_table_entry (file, "\n(code ", entry->code, ")");
1398       lf_printf (file, "\n(is_internal %d)", entry->is_internal);
1399       lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
1400     }
1401   lf_printf (file, "%s", suffix);
1402 }
1403 
1404 static void
dump_function_entries(lf * file,char * prefix,function_entry * entry,char * suffix)1405 dump_function_entries (lf *file,
1406 		       char *prefix, function_entry * entry, char *suffix)
1407 {
1408   lf_printf (file, "%s", prefix);
1409   lf_indent (file, +1);
1410   while (entry != NULL)
1411     {
1412       dump_function_entry (file, "\n(", entry, ")");
1413       entry = entry->next;
1414     }
1415   lf_indent (file, -1);
1416   lf_printf (file, "%s", suffix);
1417 }
1418 
1419 static char *
cache_entry_type_to_str(cache_entry_type type)1420 cache_entry_type_to_str (cache_entry_type type)
1421 {
1422   switch (type)
1423     {
1424     case scratch_value:
1425       return "scratch";
1426     case cache_value:
1427       return "cache";
1428     case compute_value:
1429       return "compute";
1430     }
1431   ERROR ("Bad switch");
1432   return 0;
1433 }
1434 
1435 static void
dump_cache_entry(lf * file,char * prefix,cache_entry * entry,char * suffix)1436 dump_cache_entry (lf *file, char *prefix, cache_entry *entry, char *suffix)
1437 {
1438   lf_printf (file, "%s(cache_entry *) 0x%lx", prefix, (long) entry);
1439   if (entry != NULL)
1440     {
1441       dump_line_ref (file, "\n(line ", entry->line, ")");
1442       dump_filter (file, "\n(flags ", entry->flags, ")");
1443       lf_printf (file, "\n(entry_type \"%s\")",
1444 		 cache_entry_type_to_str (entry->entry_type));
1445       lf_printf (file, "\n(name \"%s\")", entry->name);
1446       dump_filter (file, "\n(original_fields ", entry->original_fields, ")");
1447       lf_printf (file, "\n(type \"%s\")", entry->type);
1448       lf_printf (file, "\n(expression \"%s\")", entry->expression);
1449       lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
1450     }
1451   lf_printf (file, "%s", suffix);
1452 }
1453 
1454 void
dump_cache_entries(lf * file,char * prefix,cache_entry * entry,char * suffix)1455 dump_cache_entries (lf *file, char *prefix, cache_entry *entry, char *suffix)
1456 {
1457   lf_printf (file, "%s", prefix);
1458   lf_indent (file, +1);
1459   while (entry != NULL)
1460     {
1461       dump_cache_entry (file, "\n(", entry, ")");
1462       entry = entry->next;
1463     }
1464   lf_indent (file, -1);
1465   lf_printf (file, "%s", suffix);
1466 }
1467 
1468 static void
dump_model_data(lf * file,char * prefix,model_data * entry,char * suffix)1469 dump_model_data (lf *file, char *prefix, model_data *entry, char *suffix)
1470 {
1471   lf_printf (file, "%s(model_data *) 0x%lx", prefix, (long) entry);
1472   if (entry != NULL)
1473     {
1474       lf_indent (file, +1);
1475       dump_line_ref (file, "\n(line ", entry->line, ")");
1476       dump_filter (file, "\n(flags ", entry->flags, ")");
1477       dump_table_entry (file, "\n(entry ", entry->entry, ")");
1478       dump_table_entry (file, "\n(code ", entry->code, ")");
1479       lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
1480       lf_indent (file, -1);
1481     }
1482   lf_printf (file, "%s", prefix);
1483 }
1484 
1485 static void
dump_model_datas(lf * file,char * prefix,model_data * entry,char * suffix)1486 dump_model_datas (lf *file, char *prefix, model_data *entry, char *suffix)
1487 {
1488   lf_printf (file, "%s", prefix);
1489   lf_indent (file, +1);
1490   while (entry != NULL)
1491     {
1492       dump_model_data (file, "\n(", entry, ")");
1493       entry = entry->next;
1494     }
1495   lf_indent (file, -1);
1496   lf_printf (file, "%s", suffix);
1497 }
1498 
1499 static void
dump_model_entry(lf * file,char * prefix,model_entry * entry,char * suffix)1500 dump_model_entry (lf *file, char *prefix, model_entry *entry, char *suffix)
1501 {
1502   lf_printf (file, "%s(model_entry *) 0x%lx", prefix, (long) entry);
1503   if (entry != NULL)
1504     {
1505       lf_indent (file, +1);
1506       dump_line_ref (file, "\n(line ", entry->line, ")");
1507       dump_filter (file, "\n(flags ", entry->flags, ")");
1508       lf_printf (file, "\n(name \"%s\")", entry->name);
1509       lf_printf (file, "\n(full_name \"%s\")", entry->full_name);
1510       lf_printf (file, "\n(unit_data \"%s\")", entry->unit_data);
1511       lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
1512       lf_indent (file, -1);
1513     }
1514   lf_printf (file, "%s", prefix);
1515 }
1516 
1517 static void
dump_model_entries(lf * file,char * prefix,model_entry * entry,char * suffix)1518 dump_model_entries (lf *file, char *prefix, model_entry *entry, char *suffix)
1519 {
1520   lf_printf (file, "%s", prefix);
1521   lf_indent (file, +1);
1522   while (entry != NULL)
1523     {
1524       dump_model_entry (file, "\n(", entry, ")");
1525       entry = entry->next;
1526     }
1527   lf_indent (file, -1);
1528   lf_printf (file, "%s", suffix);
1529 }
1530 
1531 
1532 static void
dump_model_table(lf * file,char * prefix,model_table * entry,char * suffix)1533 dump_model_table (lf *file, char *prefix, model_table *entry, char *suffix)
1534 {
1535   lf_printf (file, "%s(model_table *) 0x%lx", prefix, (long) entry);
1536   if (entry != NULL)
1537     {
1538       lf_indent (file, +1);
1539       dump_filter (file, "\n(processors ", entry->processors, ")");
1540       lf_printf (file, "\n(nr_models %d)", entry->nr_models);
1541       dump_model_entries (file, "\n(models ", entry->models, ")");
1542       dump_model_datas (file, "\n(macros ", entry->macros, ")");
1543       dump_model_datas (file, "\n(data ", entry->data, ")");
1544       dump_function_entries (file, "\n(statics ", entry->statics, ")");
1545       dump_function_entries (file, "\n(internals ", entry->functions, ")");
1546       dump_function_entries (file, "\n(functions ", entry->functions, ")");
1547       lf_indent (file, -1);
1548     }
1549   lf_printf (file, "%s", suffix);
1550 }
1551 
1552 
1553 static char *
insn_field_type_to_str(insn_field_type type)1554 insn_field_type_to_str (insn_field_type type)
1555 {
1556   switch (type)
1557     {
1558     case insn_field_invalid:
1559       ASSERT (0);
1560       return "(invalid)";
1561     case insn_field_int:
1562       return "int";
1563     case insn_field_reserved:
1564       return "reserved";
1565     case insn_field_wild:
1566       return "wild";
1567     case insn_field_string:
1568       return "string";
1569     }
1570   ERROR ("bad switch");
1571   return 0;
1572 }
1573 
1574 void
dump_insn_field(lf * file,char * prefix,insn_field_entry * field,char * suffix)1575 dump_insn_field (lf *file,
1576 		 char *prefix, insn_field_entry *field, char *suffix)
1577 {
1578   char *sep = " ";
1579   lf_printf (file, "%s(insn_field_entry *) 0x%lx", prefix, (long) field);
1580   if (field != NULL)
1581     {
1582       lf_indent (file, +1);
1583       lf_printf (file, "%s(first %d)", sep, field->first);
1584       lf_printf (file, "%s(last %d)", sep, field->last);
1585       lf_printf (file, "%s(width %d)", sep, field->width);
1586       lf_printf (file, "%s(type %s)", sep,
1587 		 insn_field_type_to_str (field->type));
1588       switch (field->type)
1589 	{
1590 	case insn_field_invalid:
1591 	  ASSERT (0);
1592 	  break;
1593 	case insn_field_int:
1594 	  lf_printf (file, "%s(val 0x%lx)", sep, (long) field->val_int);
1595 	  break;
1596 	case insn_field_reserved:
1597 	  /* nothing output */
1598 	  break;
1599 	case insn_field_wild:
1600 	  /* nothing output */
1601 	  break;
1602 	case insn_field_string:
1603 	  lf_printf (file, "%s(val \"%s\")", sep, field->val_string);
1604 	  break;
1605 	}
1606       lf_printf (file, "%s(next 0x%lx)", sep, (long) field->next);
1607       lf_printf (file, "%s(prev 0x%lx)", sep, (long) field->prev);
1608       lf_indent (file, -1);
1609     }
1610   lf_printf (file, "%s", suffix);
1611 }
1612 
1613 void
dump_insn_word_entry(lf * file,char * prefix,insn_word_entry * word,char * suffix)1614 dump_insn_word_entry (lf *file,
1615 		      char *prefix, insn_word_entry *word, char *suffix)
1616 {
1617   lf_printf (file, "%s(insn_word_entry *) 0x%lx", prefix, (long) word);
1618   if (word != NULL)
1619     {
1620       int i;
1621       insn_field_entry *field;
1622       lf_indent (file, +1);
1623       lf_printf (file, "\n(first 0x%lx)", (long) word->first);
1624       lf_printf (file, "\n(last 0x%lx)", (long) word->last);
1625       lf_printf (file, "\n(bit");
1626       for (i = 0; i < options.insn_bit_size; i++)
1627 	lf_printf (file, "\n ((value %d) (mask %d) (field 0x%lx))",
1628 		   word->bit[i]->value, word->bit[i]->mask,
1629 		   (long) word->bit[i]->field);
1630       lf_printf (file, ")");
1631       for (field = word->first; field != NULL; field = field->next)
1632 	dump_insn_field (file, "\n(", field, ")");
1633       dump_filter (file, "\n(field_names ", word->field_names, ")");
1634       lf_printf (file, "\n(next 0x%lx)", (long) word->next);
1635       lf_indent (file, -1);
1636     }
1637   lf_printf (file, "%s", suffix);
1638 }
1639 
1640 static void
dump_insn_word_entries(lf * file,char * prefix,insn_word_entry * word,char * suffix)1641 dump_insn_word_entries (lf *file,
1642 			char *prefix, insn_word_entry *word, char *suffix)
1643 {
1644   lf_printf (file, "%s", prefix);
1645   while (word != NULL)
1646     {
1647       dump_insn_word_entry (file, "\n(", word, ")");
1648       word = word->next;
1649     }
1650   lf_printf (file, "%s", suffix);
1651 }
1652 
1653 static void
dump_insn_model_entry(lf * file,char * prefix,insn_model_entry * model,char * suffix)1654 dump_insn_model_entry (lf *file,
1655 		       char *prefix, insn_model_entry *model, char *suffix)
1656 {
1657   lf_printf (file, "%s(insn_model_entry *) 0x%lx", prefix, (long) model);
1658   if (model != NULL)
1659     {
1660       lf_indent (file, +1);
1661       dump_line_ref (file, "\n(line ", model->line, ")");
1662       dump_filter (file, "\n(names ", model->names, ")");
1663       lf_printf (file, "\n(full_name \"%s\")", model->full_name);
1664       lf_printf (file, "\n(unit_data \"%s\")", model->unit_data);
1665       lf_printf (file, "\n(insn (insn_entry *) 0x%lx)", (long) model->insn);
1666       lf_printf (file, "\n(next (insn_model_entry *) 0x%lx)",
1667 		 (long) model->next);
1668       lf_indent (file, -1);
1669     }
1670   lf_printf (file, "%s", suffix);
1671 }
1672 
1673 static void
dump_insn_model_entries(lf * file,char * prefix,insn_model_entry * model,char * suffix)1674 dump_insn_model_entries (lf *file,
1675 			 char *prefix, insn_model_entry *model, char *suffix)
1676 {
1677   lf_printf (file, "%s", prefix);
1678   while (model != NULL)
1679     {
1680       dump_insn_model_entry (file, "\n", model, "");
1681       model = model->next;
1682     }
1683   lf_printf (file, "%s", suffix);
1684 }
1685 
1686 
1687 static void
dump_insn_mnemonic_entry(lf * file,char * prefix,insn_mnemonic_entry * mnemonic,char * suffix)1688 dump_insn_mnemonic_entry (lf *file,
1689 			  char *prefix,
1690 			  insn_mnemonic_entry *mnemonic, char *suffix)
1691 {
1692   lf_printf (file, "%s(insn_mnemonic_entry *) 0x%lx", prefix,
1693 	     (long) mnemonic);
1694   if (mnemonic != NULL)
1695     {
1696       lf_indent (file, +1);
1697       dump_line_ref (file, "\n(line ", mnemonic->line, ")");
1698       lf_printf (file, "\n(format \"%s\")", mnemonic->format);
1699       lf_printf (file, "\n(condition \"%s\")", mnemonic->condition);
1700       lf_printf (file, "\n(insn (insn_entry *) 0x%lx)",
1701 		 (long) mnemonic->insn);
1702       lf_printf (file, "\n(next (insn_mnemonic_entry *) 0x%lx)",
1703 		 (long) mnemonic->next);
1704       lf_indent (file, -1);
1705     }
1706   lf_printf (file, "%s", suffix);
1707 }
1708 
1709 static void
dump_insn_mnemonic_entries(lf * file,char * prefix,insn_mnemonic_entry * mnemonic,char * suffix)1710 dump_insn_mnemonic_entries (lf *file,
1711 			    char *prefix,
1712 			    insn_mnemonic_entry *mnemonic, char *suffix)
1713 {
1714   lf_printf (file, "%s", prefix);
1715   while (mnemonic != NULL)
1716     {
1717       dump_insn_mnemonic_entry (file, "\n", mnemonic, "");
1718       mnemonic = mnemonic->next;
1719     }
1720   lf_printf (file, "%s", suffix);
1721 }
1722 
1723 void
dump_insn_entry(lf * file,char * prefix,insn_entry * entry,char * suffix)1724 dump_insn_entry (lf *file, char *prefix, insn_entry * entry, char *suffix)
1725 {
1726   lf_printf (file, "%s(insn_entry *) 0x%lx", prefix, (long) entry);
1727   if (entry != NULL)
1728     {
1729       int i;
1730       lf_indent (file, +1);
1731       dump_line_ref (file, "\n(line ", entry->line, ")");
1732       dump_filter (file, "\n(flags ", entry->flags, ")");
1733       lf_printf (file, "\n(nr_words %d)", entry->nr_words);
1734       dump_insn_word_entries (file, "\n(words ", entry->words, ")");
1735       lf_printf (file, "\n(word");
1736       for (i = 0; i < entry->nr_models; i++)
1737 	lf_printf (file, " 0x%lx", (long) entry->word[i]);
1738       lf_printf (file, ")");
1739       dump_filter (file, "\n(field_names ", entry->field_names, ")");
1740       lf_printf (file, "\n(format_name \"%s\")", entry->format_name);
1741       dump_filter (file, "\n(options ", entry->options, ")");
1742       lf_printf (file, "\n(name \"%s\")", entry->name);
1743       lf_printf (file, "\n(nr_models %d)", entry->nr_models);
1744       dump_insn_model_entries (file, "\n(models ", entry->models, ")");
1745       lf_printf (file, "\n(model");
1746       for (i = 0; i < entry->nr_models; i++)
1747 	lf_printf (file, " 0x%lx", (long) entry->model[i]);
1748       lf_printf (file, ")");
1749       dump_filter (file, "\n(processors ", entry->processors, ")");
1750       dump_insn_mnemonic_entries (file, "\n(mnemonics ", entry->mnemonics,
1751 				  ")");
1752       dump_table_entry (file, "\n(code ", entry->code, ")");
1753       lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
1754       lf_indent (file, -1);
1755     }
1756   lf_printf (file, "%s", suffix);
1757 }
1758 
1759 static void
dump_insn_entries(lf * file,char * prefix,insn_entry * entry,char * suffix)1760 dump_insn_entries (lf *file, char *prefix, insn_entry * entry, char *suffix)
1761 {
1762   lf_printf (file, "%s", prefix);
1763   lf_indent (file, +1);
1764   while (entry != NULL)
1765     {
1766       dump_insn_entry (file, "\n(", entry, ")");
1767       entry = entry->next;
1768     }
1769   lf_indent (file, -1);
1770   lf_printf (file, "%s", suffix);
1771 }
1772 
1773 
1774 
1775 void
dump_insn_table(lf * file,char * prefix,insn_table * isa,char * suffix)1776 dump_insn_table (lf *file, char *prefix, insn_table *isa, char *suffix)
1777 {
1778   lf_printf (file, "%s(insn_table *) 0x%lx", prefix, (long) isa);
1779   if (isa != NULL)
1780     {
1781       lf_indent (file, +1);
1782       dump_cache_entries (file, "\n(caches ", isa->caches, ")");
1783       lf_printf (file, "\n(nr_insns %d)", isa->nr_insns);
1784       lf_printf (file, "\n(max_nr_words %d)", isa->max_nr_words);
1785       dump_insn_entries (file, "\n(insns ", isa->insns, ")");
1786       dump_function_entries (file, "\n(functions ", isa->functions, ")");
1787       dump_insn_entry (file, "\n(illegal_insn ", isa->illegal_insn, ")");
1788       dump_model_table (file, "\n(model ", isa->model, ")");
1789       dump_filter (file, "\n(flags ", isa->flags, ")");
1790       dump_filter (file, "\n(options ", isa->options, ")");
1791       lf_indent (file, -1);
1792     }
1793   lf_printf (file, "%s", suffix);
1794 }
1795 
1796 #ifdef MAIN
1797 
1798 igen_options options;
1799 
1800 int
main(int argc,char ** argv)1801 main (int argc, char **argv)
1802 {
1803   insn_table *isa;
1804   lf *l;
1805 
1806   INIT_OPTIONS (options);
1807 
1808   if (argc == 3)
1809     filter_parse (&options.flags_filter, argv[2]);
1810   else if (argc != 2)
1811     error (NULL, "Usage: insn <insn-table> [ <filter-in> ]\n");
1812 
1813   isa = load_insn_table (argv[1], NULL);
1814   l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn");
1815   dump_insn_table (l, "(isa ", isa, ")\n");
1816 
1817   return 0;
1818 }
1819 
1820 #endif
1821