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