xref: /netbsd-src/external/gpl3/gdb/dist/sim/igen/gen-idecode.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2 
3    Copyright 2002-2020 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 
29 #include "ld-insn.h"
30 #include "ld-decode.h"
31 
32 #include "gen.h"
33 
34 #include "gen-idecode.h"
35 #include "gen-icache.h"
36 #include "gen-semantics.h"
37 
38 
39 
40 static void
41 lf_print_opcodes (lf *file, gen_entry *table)
42 {
43   if (table !=NULL)
44     {
45       while (1)
46 	{
47 	  ASSERT (table->opcode != NULL);
48 	  lf_printf (file, "_%d_%d",
49 		     table->opcode->first, table->opcode->last);
50 	  if (table->parent == NULL)
51 	    break;
52 	  lf_printf (file, "__%d", table->opcode_nr);
53 	  table = table->parent;
54 	}
55     }
56 }
57 
58 
59 
60 
61 static void
62 print_idecode_ifetch (lf *file,
63 		      int previous_nr_prefetched_words,
64 		      int current_nr_prefetched_words)
65 {
66   int word_nr;
67   for (word_nr = previous_nr_prefetched_words;
68        word_nr < current_nr_prefetched_words; word_nr++)
69     {
70       lf_printf (file,
71 		 "instruction_word instruction_%d = IMEM%d_IMMED (cia, %d);\n",
72 		 word_nr, options.insn_bit_size, word_nr);
73 
74     }
75 }
76 
77 
78 
79 /****************************************************************/
80 
81 
82 static void
83 lf_print_table_name (lf *file, gen_entry *table)
84 {
85   lf_printf (file, "idecode_table");
86   lf_print_opcodes (file, table);
87 }
88 
89 
90 
91 static void
92 print_idecode_table (lf *file, gen_entry *entry, const char *result)
93 {
94   lf_printf (file, "/* prime the search */\n");
95   lf_printf (file, "idecode_table_entry *table = ");
96   lf_print_table_name (file, entry);
97   lf_printf (file, ";\n");
98   lf_printf (file, "int opcode = EXTRACTED%d (instruction, %d, %d);\n",
99 	     options.insn_bit_size,
100 	     i2target (options.hi_bit_nr, entry->opcode->first),
101 	     i2target (options.hi_bit_nr, entry->opcode->last));
102   lf_printf (file, "idecode_table_entry *table_entry = table + opcode;\n");
103 
104   lf_printf (file, "\n");
105   lf_printf (file, "/* iterate until a leaf */\n");
106   lf_printf (file, "while (1) {\n");
107   lf_printf (file, "  signed shift = table_entry->shift;\n");
108   lf_printf (file, "if (shift == function_entry) break;\n");
109   lf_printf (file, "  if (shift >= 0) {\n");
110   lf_printf (file, "    table = ((idecode_table_entry*)\n");
111   lf_printf (file, "             table_entry->function_or_table);\n");
112   lf_printf (file, "    opcode = ((instruction & table_entry->mask)\n");
113   lf_printf (file, "              >> shift);\n");
114   lf_printf (file, "    table_entry = table + opcode;\n");
115   lf_printf (file, "  }\n");
116   lf_printf (file, "  else {\n");
117   lf_printf (file, "    /* must be a boolean */\n");
118   lf_printf (file, "    ASSERT(table_entry->shift == boolean_entry);\n");
119   lf_printf (file, "    opcode = ((instruction & table_entry->mask)\n");
120   lf_printf (file, "              != table_entry->value);\n");
121   lf_printf (file, "    table = ((idecode_table_entry*)\n");
122   lf_printf (file, "             table_entry->function_or_table);\n");
123   lf_printf (file, "    table_entry = table + opcode;\n");
124   lf_printf (file, "  }\n");
125   lf_printf (file, "}\n");
126 
127   lf_printf (file, "\n");
128   lf_printf (file, "/* call the leaf code */\n");
129   if (options.gen.code == generate_jumps)
130     {
131       lf_printf (file, "goto *table_entry->function_or_table;\n");
132     }
133   else
134     {
135       lf_printf (file, "%s ", result);
136       if (options.gen.icache)
137 	{
138 	  lf_printf (file,
139 		     "(((idecode_icache*)table_entry->function_or_table)\n");
140 	  lf_printf (file, "  (");
141 	  print_icache_function_actual (file, 1);
142 	  lf_printf (file, "));\n");
143 	}
144       else
145 	{
146 	  lf_printf (file,
147 		     "((idecode_semantic*)table_entry->function_or_table)\n");
148 	  lf_printf (file, "  (");
149 	  print_semantic_function_actual (file, 1);
150 	  lf_printf (file, ");\n");
151 	}
152     }
153 }
154 
155 
156 static void
157 print_idecode_table_start (lf *file, gen_entry *table, int depth, void *data)
158 {
159   ASSERT (depth == 0);
160   /* start of the table */
161   if (table->opcode_rule->gen == array_gen)
162     {
163       lf_printf (file, "\n");
164       lf_printf (file, "static idecode_table_entry ");
165       lf_print_table_name (file, table);
166       lf_printf (file, "[] = {\n");
167     }
168 }
169 
170 static void
171 print_idecode_table_leaf (lf *file, gen_entry *entry, int depth, void *data)
172 {
173   gen_entry *master_entry;
174   ASSERT (entry->parent != NULL);
175   ASSERT (depth == 0);
176   if (entry->combined_parent == NULL)
177     master_entry = entry;
178   else
179     master_entry = entry->combined_parent;
180 
181   /* add an entry to the table */
182   if (entry->parent->opcode_rule->gen == array_gen)
183     {
184       lf_printf (file, "  /*%d*/ { ", entry->opcode_nr);
185       if (entry->opcode == NULL)
186 	{
187 	  ASSERT (entry->nr_insns == 1);
188 	  /* table leaf entry */
189 	  lf_printf (file, "function_entry, 0, 0, ");
190 	  if (options.gen.code == generate_jumps)
191 	    {
192 	      lf_printf (file, "&&");
193 	    }
194 	  print_function_name (file,
195 			       entry->insns->insn->name,
196 			       entry->insns->insn->format_name,
197 			       NULL,
198 			       master_entry->expanded_bits,
199 			       (options.gen.icache
200 				? function_name_prefix_icache
201 				: function_name_prefix_semantics));
202 	}
203       else if (entry->opcode_rule->gen == switch_gen
204 	       || entry->opcode_rule->gen == goto_switch_gen
205 	       || entry->opcode_rule->gen == padded_switch_gen)
206 	{
207 	  /* table calling switch statement */
208 	  lf_printf (file, "function_entry, 0, 0, ");
209 	  if (options.gen.code == generate_jumps)
210 	    {
211 	      lf_printf (file, "&&");
212 	    }
213 	  lf_print_table_name (file, entry);
214 	}
215       else if (entry->opcode->is_boolean)
216 	{
217 	  /* table `calling' boolean table */
218 	  lf_printf (file, "boolean_entry, ");
219 	  lf_printf (file, "MASK32(%d, %d), ",
220 		     i2target (options.hi_bit_nr, entry->opcode->first),
221 		     i2target (options.hi_bit_nr, entry->opcode->last));
222 	  lf_printf (file, "INSERTED32(%d, %d, %d), ",
223 		     entry->opcode->boolean_constant,
224 		     i2target (options.hi_bit_nr, entry->opcode->first),
225 		     i2target (options.hi_bit_nr, entry->opcode->last));
226 	  lf_print_table_name (file, entry);
227 	}
228       else
229 	{
230 	  /* table `calling' another table */
231 	  lf_printf (file, "%d, ",
232 		     options.insn_bit_size - entry->opcode->last - 1);
233 	  lf_printf (file, "MASK%d(%d,%d), ", options.insn_bit_size,
234 		     i2target (options.hi_bit_nr, entry->opcode->first),
235 		     i2target (options.hi_bit_nr, entry->opcode->last));
236 	  lf_printf (file, "0, ");
237 	  lf_print_table_name (file, entry);
238 	}
239       lf_printf (file, " },\n");
240     }
241 }
242 
243 static void
244 print_idecode_table_end (lf *file, gen_entry *table, int depth, void *data)
245 {
246   ASSERT (depth == 0);
247   if (table->opcode_rule->gen == array_gen)
248     {
249       lf_printf (file, "};\n");
250     }
251 }
252 
253 /****************************************************************/
254 
255 
256 static void
257 print_goto_switch_name (lf *file, gen_entry *entry)
258 {
259   lf_printf (file, "case_");
260   if (entry->opcode == NULL)
261     {
262       print_function_name (file,
263 			   entry->insns->insn->name,
264 			   entry->insns->insn->format_name,
265 			   NULL,
266 			   entry->expanded_bits,
267 			   (options.gen.icache
268 			    ? function_name_prefix_icache
269 			    : function_name_prefix_semantics));
270     }
271   else
272     {
273       lf_print_table_name (file, entry);
274     }
275 }
276 
277 static void
278 print_goto_switch_table_leaf (lf *file,
279 			      gen_entry *entry, int depth, void *data)
280 {
281   ASSERT (entry->parent != NULL);
282   ASSERT (depth == 0);
283   ASSERT (entry->parent->opcode_rule->gen == goto_switch_gen);
284   ASSERT (entry->parent->opcode);
285 
286   lf_printf (file, "/* %d */ &&", entry->opcode_nr);
287   if (entry->combined_parent != NULL)
288     print_goto_switch_name (file, entry->combined_parent);
289   else
290     print_goto_switch_name (file, entry);
291   lf_printf (file, ",\n");
292 }
293 
294 static void
295 print_goto_switch_break (lf *file, gen_entry *entry)
296 {
297   lf_printf (file, "goto break_");
298   lf_print_table_name (file, entry->parent);
299   lf_printf (file, ";\n");
300 }
301 
302 
303 static void
304 print_goto_switch_table (lf *file, gen_entry *table)
305 {
306   lf_printf (file, "const static void *");
307   lf_print_table_name (file, table);
308   lf_printf (file, "[] = {\n");
309   lf_indent (file, +2);
310   gen_entry_traverse_tree (file, table, 0, NULL /*start */ ,
311 			   print_goto_switch_table_leaf, NULL /*end */ ,
312 			   NULL /*data */ );
313   lf_indent (file, -2);
314   lf_printf (file, "};\n");
315 }
316 
317 
318 void print_idecode_switch (lf *file, gen_entry *table, const char *result);
319 
320 static void
321 print_idecode_switch_start (lf *file, gen_entry *table, int depth, void *data)
322 {
323   /* const char *result = data; */
324   ASSERT (depth == 0);
325   ASSERT (table->opcode_rule->gen == switch_gen
326 	  || table->opcode_rule->gen == goto_switch_gen
327 	  || table->opcode_rule->gen == padded_switch_gen);
328 
329   if (table->opcode->is_boolean
330       || table->opcode_rule->gen == switch_gen
331       || table->opcode_rule->gen == padded_switch_gen)
332     {
333       lf_printf (file, "switch (EXTRACTED%d (instruction_%d, %d, %d))\n",
334 		 options.insn_bit_size,
335 		 table->opcode_rule->word_nr,
336 		 i2target (options.hi_bit_nr, table->opcode->first),
337 		 i2target (options.hi_bit_nr, table->opcode->last));
338       lf_indent (file, +2);
339       lf_printf (file, "{\n");
340     }
341   else if (table->opcode_rule->gen == goto_switch_gen)
342     {
343       if (table->parent != NULL
344 	  && (table->parent->opcode_rule->gen == switch_gen
345 	      || table->parent->opcode_rule->gen == goto_switch_gen
346 	      || table->parent->opcode_rule->gen == padded_switch_gen))
347 	{
348 	  lf_printf (file, "{\n");
349 	  lf_indent (file, +2);
350 	}
351       print_goto_switch_table (file, table);
352       lf_printf (file, "ASSERT (EXTRACTED%d (instruction_%d, %d, %d)\n",
353 		 options.insn_bit_size,
354 		 table->opcode->word_nr,
355 		 i2target (options.hi_bit_nr, table->opcode->first),
356 		 i2target (options.hi_bit_nr, table->opcode->last));
357       lf_printf (file, "        < (sizeof (");
358       lf_print_table_name (file, table);
359       lf_printf (file, ") / sizeof(void*)));\n");
360       lf_printf (file, "goto *");
361       lf_print_table_name (file, table);
362       lf_printf (file, "[EXTRACTED%d (instruction_%d, %d, %d)];\n",
363 		 options.insn_bit_size,
364 		 table->opcode->word_nr,
365 		 i2target (options.hi_bit_nr, table->opcode->first),
366 		 i2target (options.hi_bit_nr, table->opcode->last));
367     }
368   else
369     {
370       ASSERT ("bad switch" == NULL);
371     }
372 }
373 
374 
375 static void
376 print_idecode_switch_leaf (lf *file, gen_entry *entry, int depth, void *data)
377 {
378   const char *result = data;
379   ASSERT (entry->parent != NULL);
380   ASSERT (depth == 0);
381   ASSERT (entry->parent->opcode_rule->gen == switch_gen
382 	  || entry->parent->opcode_rule->gen == goto_switch_gen
383 	  || entry->parent->opcode_rule->gen == padded_switch_gen);
384   ASSERT (entry->parent->opcode);
385 
386   /* skip over any instructions combined into another entry */
387   if (entry->combined_parent != NULL)
388     return;
389 
390   if (entry->parent->opcode->is_boolean && entry->opcode_nr == 0)
391     {
392       /* case: boolean false target */
393       lf_printf (file, "case %d:\n", entry->parent->opcode->boolean_constant);
394     }
395   else if (entry->parent->opcode->is_boolean && entry->opcode_nr != 0)
396     {
397       /* case: boolean true case */
398       lf_printf (file, "default:\n");
399     }
400   else if (entry->parent->opcode_rule->gen == switch_gen
401 	   || entry->parent->opcode_rule->gen == padded_switch_gen)
402     {
403       /* case: <opcode-nr> - switch */
404       gen_entry *cob;
405       for (cob = entry; cob != NULL; cob = cob->combined_next)
406 	lf_printf (file, "case %d:\n", cob->opcode_nr);
407     }
408   else if (entry->parent->opcode_rule->gen == goto_switch_gen)
409     {
410       /* case: <opcode-nr> - goto-switch */
411       print_goto_switch_name (file, entry);
412       lf_printf (file, ":\n");
413     }
414   else
415     {
416       ERROR ("bad switch");
417     }
418   lf_printf (file, "  {\n");
419   lf_indent (file, +4);
420   {
421     if (entry->opcode == NULL)
422       {
423 	/* switch calling leaf */
424 	ASSERT (entry->nr_insns == 1);
425 	print_idecode_ifetch (file, entry->nr_prefetched_words,
426 			      entry->insns->semantic->nr_prefetched_words);
427 	switch (options.gen.code)
428 	  {
429 	  case generate_jumps:
430 	    lf_printf (file, "goto ");
431 	    break;
432 	  case generate_calls:
433 	    lf_printf (file, "%s", result);
434 	    break;
435 	  }
436 	print_function_name (file,
437 			     entry->insns->insn->name,
438 			     entry->insns->insn->format_name,
439 			     NULL,
440 			     entry->expanded_bits,
441 			     (options.gen.icache
442 			      ? function_name_prefix_icache
443 			      : function_name_prefix_semantics));
444 	if (options.gen.code == generate_calls)
445 	  {
446 	    lf_printf (file, " (");
447 	    print_semantic_function_actual (file,
448 					    entry->insns->semantic->
449 					    nr_prefetched_words);
450 	    lf_printf (file, ")");
451 	  }
452 	lf_printf (file, ";\n");
453       }
454     else if (entry->opcode_rule->gen == switch_gen
455 	     || entry->opcode_rule->gen == goto_switch_gen
456 	     || entry->opcode_rule->gen == padded_switch_gen)
457       {
458 	/* switch calling switch */
459 	lf_printf (file, "{\n");
460 	lf_indent (file, +2);
461 	print_idecode_ifetch (file, entry->parent->nr_prefetched_words,
462 			      entry->nr_prefetched_words);
463 	print_idecode_switch (file, entry, result);
464 	lf_indent (file, -2);
465 	lf_printf (file, "}\n");
466       }
467     else
468       {
469 	/* switch looking up a table */
470 	lf_printf (file, "{\n");
471 	lf_indent (file, +2);
472 	print_idecode_ifetch (file, entry->parent->nr_prefetched_words,
473 			      entry->nr_prefetched_words);
474 	print_idecode_table (file, entry, result);
475 	lf_indent (file, -2);
476 	lf_printf (file, "}\n");
477       }
478     if (entry->parent->opcode->is_boolean
479 	|| entry->parent->opcode_rule->gen == switch_gen
480 	|| entry->parent->opcode_rule->gen == padded_switch_gen)
481       {
482 	lf_printf (file, "break;\n");
483       }
484     else if (entry->parent->opcode_rule->gen == goto_switch_gen)
485       {
486 	print_goto_switch_break (file, entry);
487       }
488     else
489       {
490 	ERROR ("bad switch");
491       }
492   }
493   lf_indent (file, -4);
494   lf_printf (file, "  }\n");
495 }
496 
497 
498 static void
499 print_idecode_switch_illegal (lf *file, const char *result)
500 {
501   lf_indent (file, +2);
502   print_idecode_invalid (file, result, invalid_illegal);
503   lf_printf (file, "break;\n");
504   lf_indent (file, -2);
505 }
506 
507 static void
508 print_idecode_switch_end (lf *file, gen_entry *table, int depth, void *data)
509 {
510   const char *result = data;
511   ASSERT (depth == 0);
512   ASSERT (table->opcode_rule->gen == switch_gen
513 	  || table->opcode_rule->gen == goto_switch_gen
514 	  || table->opcode_rule->gen == padded_switch_gen);
515   ASSERT (table->opcode);
516 
517   if (table->opcode->is_boolean)
518     {
519       lf_printf (file, "}\n");
520       lf_indent (file, -2);
521     }
522   else if (table->opcode_rule->gen == switch_gen
523 	   || table->opcode_rule->gen == padded_switch_gen)
524     {
525       lf_printf (file, "default:\n");
526       lf_indent (file, +2);
527       if (table->nr_entries == table->opcode->nr_opcodes)
528 	{
529 	  print_sim_engine_abort (file,
530 				  "Internal error - bad switch generated");
531 	  lf_printf (file, "%sNULL_CIA;\n", result);
532 	  lf_printf (file, "break;\n");
533 	}
534       else
535 	{
536 	  print_idecode_switch_illegal (file, result);
537 	}
538       lf_indent (file, -2);
539       lf_printf (file, "}\n");
540       lf_indent (file, -2);
541     }
542   else if (table->opcode_rule->gen == goto_switch_gen)
543     {
544       lf_printf (file, "illegal_");
545       lf_print_table_name (file, table);
546       lf_printf (file, ":\n");
547       print_idecode_invalid (file, result, invalid_illegal);
548       lf_printf (file, "break_");
549       lf_print_table_name (file, table);
550       lf_printf (file, ":;\n");
551       if (table->parent != NULL
552 	  && (table->parent->opcode_rule->gen == switch_gen
553 	      || table->parent->opcode_rule->gen == goto_switch_gen
554 	      || table->parent->opcode_rule->gen == padded_switch_gen))
555 	{
556 	  lf_indent (file, -2);
557 	  lf_printf (file, "}\n");
558 	}
559     }
560   else
561     {
562       ERROR ("bad switch");
563     }
564 }
565 
566 
567 void
568 print_idecode_switch (lf *file, gen_entry *table, const char *result)
569 {
570   gen_entry_traverse_tree (file, table,
571 			   0,
572 			   print_idecode_switch_start,
573 			   print_idecode_switch_leaf,
574 			   print_idecode_switch_end, (void *) result);
575 }
576 
577 
578 static void
579 print_idecode_switch_function_header (lf *file,
580 				      gen_entry *table,
581 				      int is_function_definition,
582 				      int nr_prefetched_words)
583 {
584   lf_printf (file, "\n");
585   if (options.gen.code == generate_calls)
586     {
587       lf_printf (file, "static ");
588       if (options.gen.icache)
589 	{
590 	  lf_printf (file, "idecode_semantic *");
591 	}
592       else
593 	{
594 	  lf_printf (file, "unsigned_word");
595 	}
596       if (is_function_definition)
597 	{
598 	  lf_printf (file, "\n");
599 	}
600       else
601 	{
602 	  lf_printf (file, " ");
603 	}
604       lf_print_table_name (file, table);
605       lf_printf (file, "\n(");
606       print_icache_function_formal (file, nr_prefetched_words);
607       lf_printf (file, ")");
608       if (!is_function_definition)
609 	{
610 	  lf_printf (file, ";");
611 	}
612       lf_printf (file, "\n");
613     }
614   if (options.gen.code == generate_jumps && is_function_definition)
615     {
616       lf_indent (file, -1);
617       lf_print_table_name (file, table);
618       lf_printf (file, ":\n");
619       lf_indent (file, +1);
620     }
621 }
622 
623 
624 static void
625 idecode_declare_if_switch (lf *file, gen_entry *table, int depth, void *data)
626 {
627   if ((table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) &&table->parent != NULL	/* don't declare the top one yet */
628       && table->parent->opcode_rule->gen == array_gen)
629     {
630       print_idecode_switch_function_header (file,
631 					    table,
632 					    0 /*isnt function definition */ ,
633 					    0);
634     }
635 }
636 
637 
638 static void
639 idecode_expand_if_switch (lf *file, gen_entry *table, int depth, void *data)
640 {
641   if ((table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) &&table->parent != NULL	/* don't expand the top one yet */
642       && table->parent->opcode_rule->gen == array_gen)
643     {
644       print_idecode_switch_function_header (file,
645 					    table,
646 					    1 /*is function definition */ ,
647 					    0);
648       if (options.gen.code == generate_calls)
649 	{
650 	  lf_printf (file, "{\n");
651 	  lf_indent (file, +2);
652 	}
653       print_idecode_switch (file, table, "return");
654       if (options.gen.code == generate_calls)
655 	{
656 	  lf_indent (file, -2);
657 	  lf_printf (file, "}\n");
658 	}
659     }
660 }
661 
662 
663 /****************************************************************/
664 
665 
666 void
667 print_idecode_lookups (lf *file, gen_entry *table, cache_entry *cache_rules)
668 {
669   int depth;
670 
671   /* output switch function declarations where needed by tables */
672   gen_entry_traverse_tree (file, table, 1, idecode_declare_if_switch,	/* START */
673 			   NULL, NULL, NULL);
674 
675   /* output tables where needed */
676   for (depth = gen_entry_depth (table); depth > 0; depth--)
677     {
678       gen_entry_traverse_tree (file, table,
679 			       1 - depth,
680 			       print_idecode_table_start,
681 			       print_idecode_table_leaf,
682 			       print_idecode_table_end, NULL);
683     }
684 
685   /* output switch functions where needed */
686   gen_entry_traverse_tree (file, table, 1, idecode_expand_if_switch,	/* START */
687 			   NULL, NULL, NULL);
688 }
689 
690 
691 void
692 print_idecode_body (lf *file, gen_entry *table, const char *result)
693 {
694   if (table->opcode_rule->gen == switch_gen
695       || table->opcode_rule->gen == goto_switch_gen
696       || table->opcode_rule->gen == padded_switch_gen)
697     {
698       print_idecode_switch (file, table, result);
699     }
700   else
701     {
702       print_idecode_table (file, table, result);
703     }
704 }
705 
706 
707 /****************************************************************/
708 
709 /* Output code to do any final checks on the decoded instruction.
710    This includes things like verifying any on decoded fields have the
711    correct value and checking that (for floating point) floating point
712    hardware isn't disabled */
713 
714 void
715 print_idecode_validate (lf *file,
716 			insn_entry * instruction, insn_opcodes *opcode_paths)
717 {
718   /* Validate: unchecked instruction fields
719 
720      If any constant fields in the instruction were not checked by the
721      idecode tables, output code to check that they have the correct
722      value here */
723   {
724     int nr_checks = 0;
725     int word_nr;
726     lf_printf (file, "\n");
727     lf_indent_suppress (file);
728     lf_printf (file, "#if defined (WITH_RESERVED_BITS)\n");
729     lf_printf (file, "/* validate: ");
730     print_insn_words (file, instruction);
731     lf_printf (file, " */\n");
732     for (word_nr = 0; word_nr < instruction->nr_words; word_nr++)
733       {
734 	insn_uint check_mask = 0;
735 	insn_uint check_val = 0;
736 	insn_word_entry *word = instruction->word[word_nr];
737 	int bit_nr;
738 
739 	/* form check_mask/check_val containing what needs to be checked
740 	   in the instruction */
741 	for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
742 	  {
743 	    insn_bit_entry *bit = word->bit[bit_nr];
744 	    insn_field_entry *field = bit->field;
745 
746 	    /* Make space for the next bit */
747 	    check_mask <<= 1;
748 	    check_val <<= 1;
749 
750 	    /* Only need to validate constant (and reserved)
751 	       bits. Skip any others */
752 	    if (field->type != insn_field_int
753 		&& field->type != insn_field_reserved
754 		/* Consider a named field equal to a value to be just as
755 		   constant as an integer field.  */
756 		&& (field->type != insn_field_string
757 		    || field->conditions == NULL
758 		    || field->conditions->test != insn_field_cond_eq
759 		    || field->conditions->type != insn_field_cond_value))
760 	      continue;
761 
762 	    /* Look through the list of opcode paths that lead to this
763 	       instruction.  See if any have failed to check the
764 	       relevant bit */
765 	    if (opcode_paths != NULL)
766 	      {
767 		insn_opcodes *entry;
768 		for (entry = opcode_paths; entry != NULL; entry = entry->next)
769 		  {
770 		    opcode_field *opcode;
771 		    for (opcode = entry->opcode;
772 			 opcode != NULL; opcode = opcode->parent)
773 		      {
774 			if (opcode->word_nr == word_nr
775 			    && opcode->first <= bit_nr
776 			    && opcode->last >= bit_nr)
777 			  /* we've decoded on this bit */
778 			  break;
779 		      }
780 		    if (opcode == NULL)
781 		      /* the bit wasn't decoded on */
782 		      break;
783 		  }
784 		if (entry == NULL)
785 		  /* all the opcode paths decoded on BIT_NR, no need
786 		     to check it */
787 		  continue;
788 	      }
789 
790 	    check_mask |= 1;
791 	    check_val |= bit->value;
792 	  }
793 
794 	/* if any bits not checked by opcode tables, output code to check them */
795 	if (check_mask)
796 	  {
797 	    if (nr_checks == 0)
798 	      {
799 		lf_printf (file, "if (WITH_RESERVED_BITS)\n");
800 		lf_printf (file, "  {\n");
801 		lf_indent (file, +4);
802 	      }
803 	    nr_checks++;
804 	    if (options.insn_bit_size > 32)
805 	      {
806 		lf_printf (file, "if ((instruction_%d\n", word_nr);
807 		lf_printf (file, "     & UNSIGNED64 (0x%08lx%08lx))\n",
808 			   (unsigned long) (check_mask >> 32),
809 			   (unsigned long) (check_mask));
810 		lf_printf (file, "    != UNSIGNED64 (0x%08lx%08lx))\n",
811 			   (unsigned long) (check_val >> 32),
812 			   (unsigned long) (check_val));
813 	      }
814 	    else
815 	      {
816 		lf_printf (file,
817 			   "if ((instruction_%d & 0x%08lx) != 0x%08lx)\n",
818 			   word_nr, (unsigned long) (check_mask),
819 			   (unsigned long) (check_val));
820 	      }
821 	    lf_indent (file, +2);
822 	    print_idecode_invalid (file, "return", invalid_illegal);
823 	    lf_indent (file, -2);
824 	  }
825       }
826     if (nr_checks > 0)
827       {
828 	lf_indent (file, -4);
829 	lf_printf (file, "  }\n");
830       }
831     lf_indent_suppress (file);
832     lf_printf (file, "#endif\n");
833   }
834 
835   /* Validate: Floating Point hardware
836 
837      If the simulator is being built with out floating point hardware
838      (different to it being disabled in the MSR) then floating point
839      instructions are invalid */
840   {
841     if (filter_is_member (instruction->flags, "f"))
842       {
843 	lf_printf (file, "\n");
844 	lf_indent_suppress (file);
845 	lf_printf (file, "#if defined(CURRENT_FLOATING_POINT)\n");
846 	lf_printf (file, "/* Validate: FP hardware exists */\n");
847 	lf_printf (file,
848 		   "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT) {\n");
849 	lf_indent (file, +2);
850 	print_idecode_invalid (file, "return", invalid_illegal);
851 	lf_indent (file, -2);
852 	lf_printf (file, "}\n");
853 	lf_indent_suppress (file);
854 	lf_printf (file, "#endif\n");
855       }
856   }
857 
858   /* Validate: Floating Point available
859 
860      If floating point is not available, we enter a floating point
861      unavailable interrupt into the cache instead of the instruction
862      proper.
863 
864      The PowerPC spec requires a CSI after MSR[FP] is changed and when
865      ever a CSI occures we flush the instruction cache. */
866 
867   {
868     if (filter_is_member (instruction->flags, "f"))
869       {
870 	lf_printf (file, "\n");
871 	lf_indent_suppress (file);
872 	lf_printf (file, "#if defined(IS_FP_AVAILABLE)\n");
873 	lf_printf (file, "/* Validate: FP available according to cpu */\n");
874 	lf_printf (file, "if (!IS_FP_AVAILABLE) {\n");
875 	lf_indent (file, +2);
876 	print_idecode_invalid (file, "return", invalid_fp_unavailable);
877 	lf_indent (file, -2);
878 	lf_printf (file, "}\n");
879 	lf_indent_suppress (file);
880 	lf_printf (file, "#endif\n");
881       }
882   }
883 
884   /* Validate: Validate Instruction in correct slot
885 
886      Some architectures place restrictions on the slot that an
887      instruction can be issued in */
888 
889   {
890     if (filter_is_member (instruction->options, "s")
891 	|| options.gen.slot_verification)
892       {
893 	lf_printf (file, "\n");
894 	lf_indent_suppress (file);
895 	lf_printf (file, "#if defined(IS_WRONG_SLOT)\n");
896 	lf_printf (file,
897 		   "/* Validate: Instruction issued in correct slot */\n");
898 	lf_printf (file, "if (IS_WRONG_SLOT) {\n");
899 	lf_indent (file, +2);
900 	print_idecode_invalid (file, "return", invalid_wrong_slot);
901 	lf_indent (file, -2);
902 	lf_printf (file, "}\n");
903 	lf_indent_suppress (file);
904 	lf_printf (file, "#endif\n");
905       }
906   }
907 
908 }
909 
910 
911 /****************************************************************/
912 
913 
914 void
915 print_idecode_issue_function_header (lf *file,
916 				     const char *processor,
917 				     function_decl_type decl_type,
918 				     int nr_prefetched_words)
919 {
920   int indent;
921   lf_printf (file, "\n");
922   switch (decl_type)
923     {
924     case is_function_declaration:
925       lf_print__function_type_function (file, print_semantic_function_type,
926 					"INLINE_IDECODE", " ");
927       break;
928     case is_function_definition:
929       lf_print__function_type_function (file, print_semantic_function_type,
930 					"INLINE_IDECODE", "\n");
931       break;
932     case is_function_variable:
933       if (lf_get_file_type (file) == lf_is_h)
934 	lf_printf (file, "extern ");
935       print_semantic_function_type (file);
936       lf_printf (file, " (*");
937       break;
938     }
939   indent = print_function_name (file,
940 				"issue",
941 				NULL,
942 				processor,
943 				NULL, function_name_prefix_idecode);
944   switch (decl_type)
945     {
946     case is_function_definition:
947       indent += lf_printf (file, " (");
948       break;
949     case is_function_declaration:
950       lf_putstr (file, "\n(");
951       indent = 1;
952       break;
953     case is_function_variable:
954       lf_putstr (file, ")\n(");
955       indent = 1;
956       break;
957     }
958   lf_indent (file, +indent);
959   print_semantic_function_formal (file, nr_prefetched_words);
960   lf_putstr (file, ")");
961   lf_indent (file, -indent);
962   switch (decl_type)
963     {
964     case is_function_definition:
965       lf_printf (file, "\n");
966       break;
967     case is_function_declaration:
968     case is_function_variable:
969       lf_putstr (file, ";\n");
970       break;
971     }
972 }
973 
974 
975 
976 void
977 print_idecode_globals (lf *file)
978 {
979   lf_printf (file, "enum {\n");
980   lf_printf (file, "  /* greater or equal to zero => table */\n");
981   lf_printf (file, "  function_entry = -1,\n");
982   lf_printf (file, "  boolean_entry = -2,\n");
983   lf_printf (file, "};\n");
984   lf_printf (file, "\n");
985   lf_printf (file, "typedef struct _idecode_table_entry {\n");
986   lf_printf (file, "  int shift;\n");
987   lf_printf (file, "  unsigned%d mask;\n", options.insn_bit_size);
988   lf_printf (file, "  unsigned%d value;\n", options.insn_bit_size);
989   lf_printf (file, "  void *function_or_table;\n");
990   lf_printf (file, "} idecode_table_entry;\n");
991 }
992