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
lf_print_opcodes(lf * file,const gen_entry * table)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
print_idecode_ifetch(lf * file,int previous_nr_prefetched_words,int current_nr_prefetched_words)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
lf_print_table_name(lf * file,const gen_entry * table)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
print_idecode_table(lf * file,const gen_entry * entry,const char * result)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
print_idecode_table_start(lf * file,const gen_entry * table,int depth,void * data)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
print_idecode_table_leaf(lf * file,const gen_entry * entry,int depth,void * data)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
print_idecode_table_end(lf * file,const gen_entry * table,int depth,void * data)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
print_goto_switch_name(lf * file,const gen_entry * entry)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
print_goto_switch_table_leaf(lf * file,const gen_entry * entry,int depth,void * data)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
print_goto_switch_break(lf * file,const gen_entry * entry)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
print_goto_switch_table(lf * file,const gen_entry * table)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
print_idecode_switch_start(lf * file,const gen_entry * table,int depth,void * data)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
print_idecode_switch_leaf(lf * file,const gen_entry * entry,int depth,void * data)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
print_idecode_switch_illegal(lf * file,const char * result)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
print_idecode_switch_end(lf * file,const gen_entry * table,int depth,void * data)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
print_idecode_switch(lf * file,const gen_entry * table,const char * result)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
print_idecode_switch_function_header(lf * file,const gen_entry * table,int is_function_definition,int nr_prefetched_words)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
idecode_declare_if_switch(lf * file,const gen_entry * table,int depth,void * data)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
idecode_expand_if_switch(lf * file,const gen_entry * table,int depth,void * data)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
print_idecode_lookups(lf * file,const gen_entry * table,cache_entry * cache_rules)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
print_idecode_body(lf * file,const gen_entry * table,const char * result)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
print_idecode_validate(lf * file,const insn_entry * instruction,const insn_opcodes * opcode_paths)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
print_idecode_issue_function_header(lf * file,const char * processor,function_decl_type decl_type,int nr_prefetched_words)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
print_idecode_globals(lf * file)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