This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / sim / igen / gen-idecode.c
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1998, Andrew Cagney <cagney@highland.com.au>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  
19     */
20
21 #include "misc.h"
22 #include "lf.h"
23 #include "table.h"
24 #include "filter.h"
25 #include "igen.h"
26
27 #include "ld-insn.h"
28 #include "ld-decode.h"
29
30 #include "gen.h"
31
32 #include "gen-idecode.h"
33 #include "gen-icache.h"
34 #include "gen-semantics.h"
35
36
37
38 static void
39 lf_print_opcodes (lf *file,
40                   gen_entry *table)
41 {
42   if (table != NULL)
43     {
44       while (1)
45         {
46           ASSERT (table->opcode != NULL);
47           lf_printf (file, "_%d_%d",
48                      table->opcode->first,
49                      table->opcode->last);
50           if (table->parent == NULL) break;
51           lf_printf (file, "__%d", table->opcode_nr);
52           table = table->parent;
53         }
54     }
55 }
56
57
58
59
60 static void
61 print_idecode_ifetch (lf *file,
62                       int previous_nr_prefetched_words,
63                       int current_nr_prefetched_words)
64 {
65   int word_nr;
66   for (word_nr = previous_nr_prefetched_words;
67        word_nr < current_nr_prefetched_words;
68        word_nr ++)
69     {
70       lf_printf (file, "instruction_word instruction_%d = IMEM%d_IMMED (cia, %d);\n",
71                  word_nr, options.insn_bit_size, word_nr);
72       
73     }
74 }
75
76
77
78 /****************************************************************/
79
80
81 static void
82 lf_print_table_name (lf *file,
83                      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,
93                      gen_entry *entry,
94                      const char *result)
95 {
96   lf_printf (file, "/* prime the search */\n");
97   lf_printf (file, "idecode_table_entry *table = ");
98   lf_print_table_name (file, entry);
99   lf_printf (file, ";\n");
100   lf_printf (file, "int opcode = EXTRACTED%d (instruction, %d, %d);\n",
101              options.insn_bit_size,
102              i2target (options.hi_bit_nr, entry->opcode->first),
103              i2target (options.hi_bit_nr, entry->opcode->last));
104   lf_printf (file, "idecode_table_entry *table_entry = table + opcode;\n");
105   
106   lf_printf (file, "\n");
107   lf_printf (file, "/* iterate until a leaf */\n");
108   lf_printf (file, "while (1) {\n");
109   lf_printf (file, "  signed shift = table_entry->shift;\n");
110   lf_printf (file, "if (shift == function_entry) break;\n");
111   lf_printf (file, "  if (shift >= 0) {\n");
112   lf_printf (file, "    table = ((idecode_table_entry*)\n");
113   lf_printf (file, "             table_entry->function_or_table);\n");
114   lf_printf (file, "    opcode = ((instruction & table_entry->mask)\n");
115   lf_printf (file, "              >> shift);\n");
116   lf_printf (file, "    table_entry = table + opcode;\n");
117   lf_printf (file, "  }\n");
118   lf_printf (file, "  else {\n");
119   lf_printf (file, "    /* must be a boolean */\n");
120   lf_printf (file, "    ASSERT(table_entry->shift == boolean_entry);\n");
121   lf_printf (file, "    opcode = ((instruction & table_entry->mask)\n");
122   lf_printf (file, "              != table_entry->value);\n");
123   lf_printf (file, "    table = ((idecode_table_entry*)\n");
124   lf_printf (file, "             table_entry->function_or_table);\n");
125   lf_printf (file, "    table_entry = table + opcode;\n");
126   lf_printf (file, "  }\n");
127   lf_printf (file, "}\n");
128   
129   lf_printf (file, "\n");
130   lf_printf (file, "/* call the leaf code */\n");
131   if (options.gen.code == generate_jumps)
132     {
133       lf_printf (file, "goto *table_entry->function_or_table;\n");
134     }
135   else
136     {
137       lf_printf (file, "%s ", result);
138       if (options.gen.icache)
139         {
140           lf_printf (file, "(((idecode_icache*)table_entry->function_or_table)\n");
141           lf_printf (file, "  (");
142           print_icache_function_actual (file, 1);
143           lf_printf (file, "));\n");
144         }
145       else
146         {
147           lf_printf (file, "((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                            gen_entry *table,
159                            int depth,
160                            void *data)
161 {
162   ASSERT (depth == 0);
163   /* start of the table */
164   if (table->opcode_rule->gen == array_gen)
165     {
166       lf_printf (file, "\n");
167       lf_printf (file, "static idecode_table_entry ");
168       lf_print_table_name (file, table);
169       lf_printf (file, "[] = {\n");
170     }
171 }
172
173 static void
174 print_idecode_table_leaf (lf *file,
175                           gen_entry *entry,
176                           int depth,
177                           void *data)
178 {
179   gen_entry *master_entry;
180   ASSERT (entry->parent != NULL);
181   ASSERT (depth == 0);
182   if (entry->combined_parent == NULL)
183     master_entry = entry;
184   else
185     master_entry = entry->combined_parent;
186
187   /* add an entry to the table */
188   if (entry->parent->opcode_rule->gen == array_gen)
189     {
190       lf_printf (file, "  /*%d*/ { ", entry->opcode_nr);
191       if (entry->opcode == NULL)
192         {
193           ASSERT (entry->nr_insns == 1);
194           /* table leaf entry */
195           lf_printf (file, "function_entry, 0, 0, ");
196           if (options.gen.code == generate_jumps)
197             {
198               lf_printf (file, "&&");
199             }
200           print_function_name (file,
201                                entry->insns->insn->name,
202                                entry->insns->insn->format_name,
203                                NULL,
204                                master_entry->expanded_bits,
205                                (options.gen.icache
206                                 ? function_name_prefix_icache
207                                 : function_name_prefix_semantics));
208         }
209       else if (entry->opcode_rule->gen == switch_gen
210                || entry->opcode_rule->gen == goto_switch_gen
211                || entry->opcode_rule->gen == padded_switch_gen)
212         {
213           /* table calling switch statement */
214           lf_printf (file, "function_entry, 0, 0, ");
215           if (options.gen.code == generate_jumps)
216             {
217               lf_printf (file, "&&");
218             }
219           lf_print_table_name (file, entry);
220         }
221       else if (entry->opcode->is_boolean)
222         {
223           /* table `calling' boolean table */
224           lf_printf (file, "boolean_entry, ");
225           lf_printf (file, "MASK32(%d, %d), ",
226                      i2target (options.hi_bit_nr, entry->opcode->first),
227                      i2target (options.hi_bit_nr, entry->opcode->last));
228           lf_printf (file, "INSERTED32(%d, %d, %d), ",
229                      entry->opcode->boolean_constant,
230                      i2target (options.hi_bit_nr, entry->opcode->first),
231                      i2target (options.hi_bit_nr, entry->opcode->last));
232           lf_print_table_name (file, entry);
233         }
234       else
235         {
236           /* table `calling' another table */
237           lf_printf (file, "%d, ", options.insn_bit_size - entry->opcode->last - 1);
238           lf_printf (file, "MASK%d(%d,%d), ",
239                      options.insn_bit_size,
240                      i2target (options.hi_bit_nr, entry->opcode->first),
241                      i2target (options.hi_bit_nr, entry->opcode->last));
242           lf_printf (file, "0, ");
243           lf_print_table_name (file, entry);
244         }
245       lf_printf (file, " },\n");
246     }
247 }
248
249 static void
250 print_idecode_table_end (lf *file,
251                          gen_entry *table,
252                          int depth,
253                          void *data)
254 {
255   ASSERT (depth == 0);
256   if (table->opcode_rule->gen == array_gen) {
257     lf_printf (file, "};\n");
258   }
259 }
260
261 /****************************************************************/
262
263
264 static void
265 print_goto_switch_name (lf *file,
266                         gen_entry *entry)
267 {
268   lf_printf (file, "case_");
269   if (entry->opcode == NULL)
270     {
271       print_function_name (file,
272                            entry->insns->insn->name,
273                            entry->insns->insn->format_name,
274                            NULL,
275                            entry->expanded_bits,
276                            (options.gen.icache
277                             ? function_name_prefix_icache
278                             : function_name_prefix_semantics));
279     }
280   else
281     {
282       lf_print_table_name(file, entry);
283     }
284 }
285
286 static void
287 print_goto_switch_table_leaf (lf *file,
288                               gen_entry *entry,
289                               int depth,
290                               void *data)
291 {
292   ASSERT (entry->parent != NULL);
293   ASSERT (depth == 0);
294   ASSERT (entry->parent->opcode_rule->gen == goto_switch_gen);
295   ASSERT (entry->parent->opcode);
296   
297   lf_printf (file, "/* %d */ &&", entry->opcode_nr);
298   if (entry->combined_parent != NULL)
299     print_goto_switch_name (file, entry->combined_parent);
300   else
301     print_goto_switch_name (file, entry);
302   lf_printf (file, ",\n");
303 }
304
305 static void
306 print_goto_switch_break (lf *file,
307                          gen_entry *entry)
308 {
309   lf_printf (file, "goto break_");
310   lf_print_table_name (file, entry->parent);
311   lf_printf (file, ";\n");
312 }
313
314
315 static void
316 print_goto_switch_table (lf *file,
317                          gen_entry *table)
318 {
319   lf_printf (file, "const static void *");
320   lf_print_table_name (file, table);
321   lf_printf (file, "[] = {\n");
322   lf_indent (file, +2);
323   gen_entry_traverse_tree (file, table,
324                            0,
325                            NULL/*start*/,
326                            print_goto_switch_table_leaf,
327                            NULL/*end*/,
328                            NULL/*data*/);
329   lf_indent (file, -2);
330   lf_printf (file, "};\n");
331 }
332
333
334 void print_idecode_switch
335 (lf *file, 
336  gen_entry *table,
337  const char *result);
338
339 static void
340 print_idecode_switch_start (lf *file,
341                             gen_entry *table,
342                             int depth,
343                             void *data)
344 {
345   /* const char *result = data; */
346   ASSERT (depth == 0);
347   ASSERT (table->opcode_rule->gen == switch_gen
348           || table->opcode_rule->gen == goto_switch_gen
349           || table->opcode_rule->gen == padded_switch_gen);
350   
351   if (table->opcode->is_boolean
352       || table->opcode_rule->gen == switch_gen
353       || table->opcode_rule->gen == padded_switch_gen)
354     {
355       lf_printf (file, "switch (EXTRACTED%d (instruction_%d, %d, %d))\n",
356                  options.insn_bit_size,
357                  table->opcode_rule->word_nr,
358                  i2target (options.hi_bit_nr, table->opcode->first),
359                  i2target (options.hi_bit_nr, table->opcode->last));
360       lf_indent (file, +2);
361       lf_printf (file, "{\n");
362     }
363   else if (table->opcode_rule->gen == goto_switch_gen)
364     {
365       if (table->parent != NULL
366           && (table->parent->opcode_rule->gen == switch_gen
367               || table->parent->opcode_rule->gen == goto_switch_gen
368               || table->parent->opcode_rule->gen == padded_switch_gen))
369         {
370           lf_printf (file, "{\n");
371           lf_indent (file, +2);
372         }
373       print_goto_switch_table (file, table);
374       lf_printf (file, "ASSERT (EXTRACTED%d (instruction_%d, %d, %d)\n",
375                  options.insn_bit_size,
376                  table->opcode->word_nr,
377                  i2target (options.hi_bit_nr, table->opcode->first),
378                  i2target (options.hi_bit_nr, table->opcode->last));
379       lf_printf (file, "        < (sizeof (");
380       lf_print_table_name (file, table);
381       lf_printf (file, ") / sizeof(void*)));\n");
382       lf_printf (file, "goto *");
383       lf_print_table_name (file, table);
384       lf_printf (file, "[EXTRACTED%d (instruction_%d, %d, %d)];\n",
385                  options.insn_bit_size,
386                  table->opcode->word_nr,
387                  i2target (options.hi_bit_nr, table->opcode->first),
388                  i2target (options.hi_bit_nr, table->opcode->last));
389     }
390   else
391     {
392       ASSERT("bad switch" == NULL);
393     }
394 }
395
396
397 static void
398 print_idecode_switch_leaf (lf *file,
399                            gen_entry *entry,
400                            int depth,
401                            void *data)
402 {
403   const char *result = data;
404   ASSERT (entry->parent != NULL);
405   ASSERT (depth == 0);
406   ASSERT (entry->parent->opcode_rule->gen == switch_gen
407           || entry->parent->opcode_rule->gen == goto_switch_gen
408           || entry->parent->opcode_rule->gen == padded_switch_gen);
409   ASSERT (entry->parent->opcode);
410   
411   /* skip over any instructions combined into another entry */
412   if (entry->combined_parent != NULL)
413     return;
414
415   if (entry->parent->opcode->is_boolean
416            && entry->opcode_nr == 0)
417     {
418       /* case: boolean false target */
419       lf_printf (file, "case %d:\n", entry->parent->opcode->boolean_constant);
420     }
421   else if (entry->parent->opcode->is_boolean
422            && entry->opcode_nr != 0)
423     {
424       /* case: boolean true case */
425       lf_printf (file, "default:\n");
426     }
427   else if (entry->parent->opcode_rule->gen == switch_gen
428            || entry->parent->opcode_rule->gen == padded_switch_gen)
429     {
430       /* case: <opcode-nr> - switch */
431       gen_entry *cob;
432       for (cob = entry; cob != NULL; cob = cob->combined_next)
433         lf_printf (file, "case %d:\n", cob->opcode_nr);
434     }
435   else if (entry->parent->opcode_rule->gen == goto_switch_gen)
436     {
437       /* case: <opcode-nr> - goto-switch */
438       print_goto_switch_name (file, entry);
439       lf_printf (file, ":\n");
440     }
441   else
442     {
443       ERROR ("bad switch");
444     }
445   lf_printf (file, "  {\n");
446   lf_indent (file, +4);
447   {
448     if (entry->opcode == NULL)
449       {
450         /* switch calling leaf */
451         ASSERT (entry->nr_insns == 1);
452         print_idecode_ifetch (file, entry->nr_prefetched_words,
453                               entry->insns->semantic->nr_prefetched_words);
454         switch (options.gen.code)
455           {
456           case generate_jumps:
457             lf_printf (file, "goto ");
458             break;
459           case generate_calls:
460             lf_printf (file, "%s", result);
461             break;
462           }
463         print_function_name (file,
464                              entry->insns->insn->name,
465                              entry->insns->insn->format_name,
466                              NULL,
467                              entry->expanded_bits,
468                              (options.gen.icache
469                               ? function_name_prefix_icache
470                               : function_name_prefix_semantics));
471         if (options.gen.code == generate_calls)
472           {
473             lf_printf (file, " (");
474             print_semantic_function_actual (file, entry->insns->semantic->nr_prefetched_words);
475             lf_printf (file, ")");
476           }
477         lf_printf (file, ";\n");
478       }
479     else if (entry->opcode_rule->gen == switch_gen
480              || entry->opcode_rule->gen == goto_switch_gen
481              || entry->opcode_rule->gen == padded_switch_gen)
482       {
483         /* switch calling switch */
484         lf_printf (file, "{\n");
485         lf_indent (file, +2);
486         print_idecode_ifetch (file, entry->parent->nr_prefetched_words,
487                               entry->nr_prefetched_words);
488         print_idecode_switch (file, entry, result);
489         lf_indent (file, -2);
490         lf_printf (file, "}\n");
491       }
492     else
493       {
494         /* switch looking up a table */
495         lf_printf (file, "{\n");
496         lf_indent (file, +2);
497         print_idecode_ifetch (file, entry->parent->nr_prefetched_words,
498                               entry->nr_prefetched_words);
499         print_idecode_table (file, entry, result);
500         lf_indent (file, -2);
501         lf_printf (file, "}\n");
502       }
503     if (entry->parent->opcode->is_boolean
504         || entry->parent->opcode_rule->gen == switch_gen
505         || entry->parent->opcode_rule->gen == padded_switch_gen)
506       {
507         lf_printf (file, "break;\n");
508       }
509     else if (entry->parent->opcode_rule->gen == goto_switch_gen)
510       {
511         print_goto_switch_break(file, entry);
512       }
513     else
514       {
515         ERROR ("bad switch");
516       }
517   }
518   lf_indent (file, -4);
519   lf_printf (file, "  }\n");
520 }
521
522
523 static void
524 print_idecode_switch_illegal (lf *file,
525                               const char *result)
526 {
527   lf_indent (file, +2);
528   print_idecode_invalid (file, result, invalid_illegal);
529   lf_printf (file, "break;\n");
530   lf_indent (file, -2);
531 }
532
533 static void
534 print_idecode_switch_end (lf *file,
535                           gen_entry *table,
536                           int depth,
537                           void *data)
538 {
539   const char *result = data;
540   ASSERT (depth == 0);
541   ASSERT (table->opcode_rule->gen == switch_gen
542           || table->opcode_rule->gen == goto_switch_gen
543           || table->opcode_rule->gen == padded_switch_gen);
544   ASSERT (table->opcode);
545   
546   if (table->opcode->is_boolean)
547     {
548       lf_printf (file, "}\n");
549       lf_indent (file, -2);
550     }
551   else if (table->opcode_rule->gen == switch_gen
552            || table->opcode_rule->gen == padded_switch_gen)
553     {
554       lf_printf (file, "default:\n");
555       lf_indent (file, +2);
556       if (table->nr_entries == table->opcode->nr_opcodes)
557         {
558           print_sim_engine_abort (file, "Internal error - bad switch generated");
559           lf_printf (file, "%sNULL_CIA;\n", result);
560           lf_printf (file, "break;\n");
561         }
562       else
563         {
564           print_idecode_switch_illegal (file, result);
565         }
566       lf_indent (file, -2);
567       lf_printf (file, "}\n");
568       lf_indent (file, -2);
569     }
570   else if (table->opcode_rule->gen == goto_switch_gen)
571     {
572       lf_printf (file, "illegal_");
573       lf_print_table_name (file, table);
574       lf_printf (file, ":\n");
575       print_idecode_invalid (file, result, invalid_illegal);
576       lf_printf (file, "break_");
577       lf_print_table_name(file, table);
578       lf_printf (file, ":;\n");
579       if (table->parent != NULL
580           && (table->parent->opcode_rule->gen == switch_gen
581               || table->parent->opcode_rule->gen == goto_switch_gen
582               || table->parent->opcode_rule->gen == padded_switch_gen))
583         {
584           lf_indent (file, -2);
585           lf_printf (file, "}\n");
586         }
587     }
588   else
589     {
590       ERROR ("bad switch");
591     }
592 }
593
594
595 void
596 print_idecode_switch (lf *file, 
597                       gen_entry *table,
598                       const char *result)
599 {
600   gen_entry_traverse_tree (file, table,
601                            0,
602                            print_idecode_switch_start,
603                            print_idecode_switch_leaf,
604                            print_idecode_switch_end,
605                            (void*)result);
606 }
607
608
609 static void
610 print_idecode_switch_function_header (lf *file,
611                                       gen_entry *table,
612                                       int is_function_definition,
613                                       int nr_prefetched_words)
614 {
615   lf_printf (file, "\n");
616   if (options.gen.code == generate_calls)
617     {
618       lf_printf (file, "static ");
619       if (options.gen.icache)
620         {
621           lf_printf (file, "idecode_semantic *");
622         }
623       else
624         {
625           lf_printf (file, "unsigned_word");
626         }
627       if (is_function_definition)
628         {
629           lf_printf (file, "\n");
630         }
631       else
632         {
633           lf_printf (file, " ");
634         }
635       lf_print_table_name (file, table);
636       lf_printf (file, "\n(");
637       print_icache_function_formal (file, nr_prefetched_words);
638       lf_printf (file, ")");
639       if (!is_function_definition)
640         {
641           lf_printf (file, ";");
642         }
643       lf_printf (file, "\n");
644     }
645   if (options.gen.code == generate_jumps && is_function_definition)
646     {
647       lf_indent (file, -1);
648       lf_print_table_name (file, table);
649       lf_printf (file, ":\n");
650       lf_indent (file, +1);
651     }
652 }
653
654
655 static void
656 idecode_declare_if_switch (lf *file,
657                            gen_entry *table,
658                            int depth,
659                            void *data)
660 {
661   if ((table->opcode_rule->gen == switch_gen
662        || table->opcode_rule->gen == goto_switch_gen
663        || table->opcode_rule->gen == padded_switch_gen)
664       && table->parent != NULL /* don't declare the top one yet */
665       && table->parent->opcode_rule->gen == array_gen)
666     {
667       print_idecode_switch_function_header (file,
668                                             table,
669                                             0/*isnt function definition*/,
670                                             0);
671     }
672 }
673
674
675 static void
676 idecode_expand_if_switch (lf *file,
677                           gen_entry *table,
678                           int depth,
679                           void *data)
680 {
681   if ((table->opcode_rule->gen == switch_gen
682        || table->opcode_rule->gen == goto_switch_gen
683        || table->opcode_rule->gen == padded_switch_gen)
684       && table->parent != NULL /* don't expand the top one yet */
685       && table->parent->opcode_rule->gen == array_gen)
686     {
687       print_idecode_switch_function_header(file,
688                                            table,
689                                            1/*is function definition*/,
690                                            0);
691       if (options.gen.code == generate_calls)
692         {
693           lf_printf (file, "{\n");
694           lf_indent (file, +2);
695         }
696       print_idecode_switch(file, table, "return");
697       if (options.gen.code == generate_calls)
698         {
699           lf_indent (file, -2);
700           lf_printf (file, "}\n");
701         }
702     }
703 }
704
705
706 /****************************************************************/
707
708
709 void
710 print_idecode_lookups (lf *file,
711                        gen_entry *table,
712                        cache_entry *cache_rules)
713 {
714   int depth;
715   
716   /* output switch function declarations where needed by tables */
717   gen_entry_traverse_tree (file, table,
718                            1,
719                            idecode_declare_if_switch, /* START */
720                            NULL, NULL,
721                            NULL);
722   
723   /* output tables where needed */
724   for (depth = gen_entry_depth (table);
725        depth > 0;
726        depth--)
727     {
728       gen_entry_traverse_tree (file, table,
729                                1-depth,
730                                print_idecode_table_start,
731                                print_idecode_table_leaf,
732                                print_idecode_table_end,
733                                NULL);
734     }
735   
736   /* output switch functions where needed */
737   gen_entry_traverse_tree (file, table,
738                             1,
739                             idecode_expand_if_switch, /* START */
740                             NULL, NULL,
741                             NULL);
742 }
743
744
745 void
746 print_idecode_body (lf *file,
747                     gen_entry *table,
748                     const char *result)
749 {
750   if (table->opcode_rule->gen == switch_gen
751       || table->opcode_rule->gen == goto_switch_gen
752       || table->opcode_rule->gen == padded_switch_gen)
753     {
754       print_idecode_switch (file, table, result);
755     }
756   else
757     {
758       print_idecode_table (file, table, result);
759     }
760 }
761
762
763 /****************************************************************/
764
765 #if 0
766 static void
767 print_jump (lf *file,
768             int is_tail)
769 {
770   if (is_tail)
771     {
772       lf_putstr (file, "if (keep_running != NULL && !*keep_running)\n");
773       lf_putstr (file, "  cpu_halt(cpu, nia, was_continuing, 0/*na*/);\n");
774     }
775   
776   if (!options.generate_smp)
777     {
778       lf_putstr (file, "if (WITH_EVENTS) {\n");
779       lf_putstr (file, "  if (event_queue_tick(events)) {\n");
780       lf_putstr (file, "    cpu_set_program_counter(cpu, nia);\n");
781       lf_putstr (file, "    event_queue_process(events);\n");
782       lf_putstr (file, "    nia = cpu_get_program_counter(cpu);\n");
783       lf_putstr (file, "  }\n");
784       lf_putstr (file, "}\n");
785     }
786   
787   if (options.generate_smp)
788     {
789       if (is_tail)
790         {
791           lf_putstr (file, "cpu_set_program_counter(cpu, nia);\n");
792         }
793       lf_putstr (file, "if (WITH_EVENTS) {\n");
794       lf_putstr (file, "  current_cpu += 1;\n");
795       lf_putstr (file, "  if (current_cpu >= nr_cpus) {\n");
796       lf_putstr (file, "    if (event_queue_tick(events)) {\n");
797       lf_putstr (file, "      event_queue_process(events);\n");
798       lf_putstr (file, "    }\n");
799       lf_putstr (file, "    current_cpu = 0;\n");
800       lf_putstr (file, "  }\n");
801       lf_putstr (file, "}\n");
802       lf_putstr (file, "else {\n");
803       lf_putstr (file, "  current_cpu = (current_cpu + 1) % nr_cpus;\n");
804       lf_putstr (file, "}\n");
805       lf_putstr (file, "cpu = cpus[current_cpu];\n");
806       lf_putstr (file, "nia = cpu_get_program_counter(cpu);\n");
807     }
808   
809   if (options.gen.icache)
810     {
811       lf_putstr (file, "cache_entry = cpu_icache_entry(cpu, nia);\n");
812       lf_putstr (file, "if (cache_entry->address == nia) {\n");
813       lf_putstr (file, "  /* cache hit */\n");
814       lf_putstr (file, "  goto *cache_entry->semantic;\n");
815       lf_putstr (file, "}\n");
816       if (is_tail)
817         {
818           lf_putstr (file, "goto cache_miss;\n");
819         }
820     }
821
822   if (!options.gen.icache && is_tail)
823     {
824       lf_printf (file, "goto idecode;\n");
825     }
826   
827 }
828 #endif
829
830
831
832 #if 0
833 static void
834 print_jump_insn (lf *file,
835                  insn_entry *instruction,
836                  insn_bits *expanded_bits,
837                  opcode_field *opcodes,
838                  cache_entry *cache_rules)
839 {
840   
841   /* what we are for the moment */
842   lf_printf (file, "\n");
843   print_my_defines (file, expanded_bits, instruction->name);
844   
845   /* output the icache entry */
846   if (options.gen.icache)
847     {
848       lf_printf (file, "\n");
849       lf_indent (file, -1);
850       print_function_name (file,
851                            instruction->name,
852                            expanded_bits,
853                            function_name_prefix_icache);
854       lf_printf (file, ":\n");
855       lf_indent (file, +1);
856       lf_printf (file, "{\n");
857       lf_indent (file, +2);
858       lf_putstr (file, "const unsigned_word cia = nia;\n");
859       print_itrace (file, instruction, 1/*putting-value-in-cache*/);
860       print_idecode_validate (file, instruction, opcodes);
861       lf_printf (file, "\n");
862       lf_printf (file, "{\n");
863       lf_indent (file, +2);
864       print_icache_body (file,
865                          instruction,
866                          expanded_bits,
867                          cache_rules,
868                          0, /*use_defines*/
869                          put_values_in_icache);
870       lf_printf (file, "cache_entry->address = nia;\n");
871       lf_printf (file, "cache_entry->semantic = &&");
872       print_function_name (file,
873                            instruction->name,
874                            expanded_bits,
875                            function_name_prefix_semantics);
876       lf_printf (file, ";\n");
877       if (options.gen.semantic_icache)
878         {
879           print_semantic_body (file,
880                                instruction,
881                                expanded_bits,
882                                opcodes);
883           print_jump (file, 1/*is-tail*/);
884         }
885       else
886         {
887           lf_printf (file, "/* goto ");
888           print_function_name (file,
889                                instruction->name,
890                                expanded_bits,
891                                function_name_prefix_semantics);
892           lf_printf (file, "; */\n");
893         }
894       lf_indent (file, -2);
895       lf_putstr (file, "}\n");
896       lf_indent (file, -2);
897       lf_printf (file, "}\n");
898     }
899   
900   /* print the semantics */
901   lf_printf (file, "\n");
902   lf_indent (file, -1);
903   print_function_name (file,
904                        instruction->name,
905                        expanded_bits,
906                        function_name_prefix_semantics);
907   lf_printf (file, ":\n");
908   lf_indent (file, +1);
909   lf_printf (file, "{\n");
910   lf_indent (file, +2);
911   lf_putstr (file, "const unsigned_word cia = nia;\n");
912   print_icache_body (file,
913                      instruction,
914                      expanded_bits,
915                      cache_rules,
916                      (options.gen.direct_access
917                       ? define_variables
918                       : declare_variables),
919                      (options.gen.icache
920                       ? get_values_from_icache
921                       : do_not_use_icache));
922   print_semantic_body (file,
923                        instruction,
924                        expanded_bits,
925                        opcodes);
926   if (options.gen.direct_access)
927     print_icache_body (file,
928                        instruction,
929                        expanded_bits,
930                        cache_rules,
931                        undef_variables,
932                        (options.gen.icache
933                         ? get_values_from_icache
934                         : do_not_use_icache));
935   print_jump (file, 1/*is tail*/);
936   lf_indent (file, -2);
937   lf_printf (file, "}\n");
938 }
939 #endif
940
941
942 #if 0
943 static void
944 print_jump_definition (lf *file,
945                        gen_entry *entry,
946                        insn_entry *insn,
947                        int depth,
948                        void *data)
949 {
950   cache_entry *cache_rules = (cache_entry*)data;
951   if (options.generate_expanded_instructions)
952     {
953       ASSERT (entry->nr_insns == 1
954               && entry->opcode == NULL
955               && entry->parent != NULL
956               && entry->parent->opcode != NULL);
957       ASSERT (entry->nr_insns == 1
958               && entry->opcode == NULL
959               && entry->parent != NULL
960               && entry->parent->opcode != NULL
961               && entry->parent->opcode_rule != NULL);
962       print_jump_insn (file,
963                        entry->insns->words[0]->insn,
964                        entry->expanded_bits,
965                        entry->opcode,
966                        cache_rules);
967     }
968   else
969     {
970       print_jump_insn (file,
971                        instruction->words[0]->insn,
972                        NULL,
973                        NULL,
974                        cache_rules);
975     }
976 }
977 #endif
978
979 #if 0
980 static void
981 print_jump_internal_function (lf *file,
982                               gen_entry *table,
983                               function_entry *function,
984                               void *data)
985 {
986   if (function->is_internal)
987     {
988       lf_printf (file, "\n");
989       lf_print__line_ref (file, function->line);
990       lf_indent (file, -1);
991       print_function_name (file,
992                            function->name,
993                            NULL,
994                            (options.gen.icache
995                             ? function_name_prefix_icache
996                             : function_name_prefix_semantics));
997       lf_printf (file, ":\n");
998       lf_indent (file, +1);
999       lf_printf (file, "{\n");
1000       lf_indent (file, +2);
1001       lf_printf (file, "const unsigned_word cia = nia;\n");
1002       table_print_code (file, function->code);
1003       lf_print__internal_ref (file);
1004       print_sim_engine_abort (file, "Internal function must longjump");
1005       lf_indent (file, -2);
1006       lf_printf (file, "}\n");
1007     }
1008 }
1009 #endif
1010
1011
1012
1013 #if 0
1014 static void
1015 print_jump_until_stop_body(lf *file,
1016                            insn_table *table,
1017                            cache_table *cache_rules)
1018 {
1019   lf_printf (file, "{\n");
1020   lf_indent (file, +2);
1021   lf_putstr (file, "jmp_buf halt;\n");
1022   lf_putstr (file, "jmp_buf restart;\n");
1023   lf_putstr (file, "sim_cpu *cpu = NULL;\n");
1024   lf_putstr (file, "unsigned_word nia = -1;\n");
1025   lf_putstr (file, "instruction_word instruction = 0;\n");
1026   if ((code & generate_with_icache)) {
1027     lf_putstr (file, "idecode_cache *cache_entry = NULL;\n");
1028   }
1029   if (generate_smp) {
1030     lf_putstr (file, "int current_cpu = -1;\n");
1031   }
1032
1033   /* all the switches and tables - they know about jumping */
1034   print_idecode_lookups(file, table, cache_rules);
1035  
1036   /* start the simulation up */
1037   if ((code & generate_with_icache)) {
1038     lf_putstr (file, "\n");
1039     lf_putstr (file, "{\n");
1040     lf_putstr (file, "  int cpu_nr;\n");
1041     lf_putstr (file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
1042     lf_putstr (file, "    cpu_flush_icache(cpus[cpu_nr]);\n");
1043     lf_putstr (file, "}\n");
1044   }
1045
1046   lf_putstr (file, "\n");
1047   lf_putstr (file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
1048
1049   lf_putstr (file, "\n");
1050   lf_putstr (file, "if (setjmp(halt))\n");
1051   lf_putstr (file, "  return;\n");
1052
1053   lf_putstr (file, "\n");
1054   lf_putstr (file, "setjmp(restart);\n");
1055
1056   lf_putstr (file, "\n");
1057   if (!generate_smp) {
1058     lf_putstr (file, "cpu = cpus[0];\n");
1059     lf_putstr (file, "nia = cpu_get_program_counter(cpu);\n");
1060   }
1061   else {
1062     lf_putstr (file, "current_cpu = psim_last_cpu(system);\n");
1063   }
1064
1065   if (!(code & generate_with_icache)) {
1066     lf_printf (file, "\n");
1067     lf_indent (file, -1);
1068     lf_printf (file, "idecode:\n");
1069     lf_indent (file, +1);
1070   }
1071
1072   print_jump(file, 0/*is_tail*/);
1073
1074   if ((code & generate_with_icache)) {
1075     lf_indent (file, -1);
1076     lf_printf (file, "cache_miss:\n");
1077     lf_indent (file, +1);
1078   }
1079
1080   lf_putstr (file, "instruction\n");
1081   lf_putstr (file, "  = vm_instruction_map_read(cpu_instruction_map(cpu),\n");
1082   lf_putstr (file, "                            cpu, nia);\n");
1083   print_idecode_body(file, table, "/*IGORE*/");
1084
1085   /* print out a table of all the internals functions */
1086   insn_table_traverse_function(table,
1087                                file, NULL,
1088                                print_jump_internal_function);
1089
1090  /* print out a table of all the instructions */
1091   if (generate_expanded_instructions)
1092     insn_table_traverse_tree(table,
1093                              file, cache_rules,
1094                              1,
1095                              NULL, /* start */
1096                              print_jump_definition, /* leaf */
1097                              NULL, /* end */
1098                              NULL); /* padding */
1099   else
1100     insn_table_traverse_insn(table,
1101                              file, cache_rules,
1102                              print_jump_definition);
1103   lf_indent (file, -2);
1104   lf_printf (file, "}\n");
1105 }
1106 #endif
1107
1108 /****************************************************************/
1109
1110
1111
1112 /* Output code to do any final checks on the decoded instruction.
1113    This includes things like verifying any on decoded fields have the
1114    correct value and checking that (for floating point) floating point
1115    hardware isn't disabled */
1116
1117 void
1118 print_idecode_validate (lf *file,
1119                         insn_entry *instruction,
1120                         insn_opcodes *opcode_paths)
1121 {
1122   /* Validate: unchecked instruction fields
1123
1124      If any constant fields in the instruction were not checked by the
1125      idecode tables, output code to check that they have the correct
1126      value here */
1127   {
1128     int nr_checks = 0;
1129     int word_nr;
1130     lf_printf (file, "\n");
1131     lf_indent_suppress (file);
1132     lf_printf (file, "#if defined (WITH_RESERVED_BITS)\n");
1133     lf_printf (file, "/* validate: ");
1134     print_insn_words (file, instruction);
1135     lf_printf (file, " */\n");
1136     for (word_nr = 0; word_nr < instruction->nr_words; word_nr++)
1137       {
1138         insn_uint check_mask = 0;
1139         insn_uint check_val = 0;
1140         insn_word_entry *word = instruction->word[word_nr];
1141         int bit_nr;
1142
1143         /* form check_mask/check_val containing what needs to be checked
1144            in the instruction */
1145         for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
1146           {
1147             insn_bit_entry *bit = word->bit[bit_nr];
1148             insn_field_entry *field = bit->field;
1149
1150             /* Make space for the next bit */
1151             check_mask <<= 1;
1152             check_val <<= 1;
1153             
1154             /* Only need to validate constant (and reserved)
1155                bits. Skip any others */
1156             if (field->type != insn_field_int
1157                 && field->type != insn_field_reserved)
1158               continue;
1159
1160             /* Look through the list of opcode paths that lead to this
1161                instruction.  See if any have failed to check the
1162                relevant bit */
1163             if (opcode_paths != NULL)
1164               {
1165                 insn_opcodes *entry;
1166                 for (entry = opcode_paths;
1167                      entry != NULL;
1168                      entry = entry->next)
1169                   {
1170                     opcode_field *opcode;
1171                     for (opcode = entry->opcode;
1172                          opcode != NULL;
1173                          opcode = opcode->parent)
1174                       {
1175                         if (opcode->word_nr == word_nr
1176                             && opcode->first <= bit_nr
1177                             && opcode->last >= bit_nr)
1178                           /* we've decoded on this bit */
1179                           break;
1180                       }
1181                     if (opcode == NULL)
1182                       /* the bit wasn't decoded on */
1183                       break;
1184                   }
1185                 if (entry == NULL)
1186                   /* all the opcode paths decoded on BIT_NR, no need
1187                      to check it */
1188                   continue;
1189               }
1190             
1191             check_mask |= 1;
1192             check_val |= bit->value;
1193           }
1194         
1195         /* if any bits not checked by opcode tables, output code to check them */
1196         if (check_mask)
1197           {
1198             if (nr_checks == 0)
1199               {
1200                 lf_printf (file, "if (WITH_RESERVED_BITS)\n");
1201                 lf_printf (file, "  {\n");
1202                 lf_indent (file, +4);
1203               }
1204             nr_checks ++;
1205             if (options.insn_bit_size > 32)
1206               {
1207                 lf_printf (file, "if ((instruction_%d\n", word_nr); 
1208                 lf_printf (file, "     & UNSIGNED64 (0x%08lx%08lx))\n",
1209                            (unsigned long)(check_mask >> 32),
1210                            (unsigned long)(check_mask));
1211                 lf_printf (file, "    != UNSIGNED64 (0x%08lx%08lx))\n",
1212                            (unsigned long)(check_val >> 32),
1213                            (unsigned long)(check_val));
1214               }
1215             else
1216               {
1217                 lf_printf (file, "if ((instruction_%d & 0x%08lx) != 0x%08lx)\n",
1218                            word_nr,
1219                            (unsigned long)(check_mask),
1220                            (unsigned long)(check_val));
1221               }
1222             lf_indent (file, +2);
1223             print_idecode_invalid (file, "return", invalid_illegal);
1224             lf_indent (file, -2);
1225           }
1226       }
1227     if (nr_checks > 0)
1228       {
1229         lf_indent (file, -4);
1230         lf_printf (file, "  }\n");
1231       }
1232     lf_indent_suppress(file);
1233     lf_printf (file, "#endif\n");
1234   }
1235
1236   /* Validate: Floating Point hardware
1237      
1238      If the simulator is being built with out floating point hardware
1239      (different to it being disabled in the MSR) then floating point
1240      instructions are invalid */
1241   {
1242     if (filter_is_member (instruction->flags, "f"))
1243       {
1244         lf_printf (file, "\n");
1245         lf_indent_suppress (file);
1246         lf_printf (file, "#if defined(CURRENT_FLOATING_POINT)\n");
1247         lf_printf (file, "/* Validate: FP hardware exists */\n");
1248         lf_printf (file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT) {\n");
1249         lf_indent (file, +2);
1250         print_idecode_invalid (file, "return", invalid_illegal);
1251         lf_indent (file, -2);
1252         lf_printf (file, "}\n");
1253         lf_indent_suppress (file);
1254         lf_printf (file, "#endif\n");
1255       }
1256   }
1257
1258   /* Validate: Floating Point available
1259
1260      If floating point is not available, we enter a floating point
1261      unavailable interrupt into the cache instead of the instruction
1262      proper.
1263
1264      The PowerPC spec requires a CSI after MSR[FP] is changed and when
1265      ever a CSI occures we flush the instruction cache. */
1266
1267   {
1268     if (filter_is_member (instruction->flags, "f"))
1269       {
1270         lf_printf (file, "\n");
1271         lf_indent_suppress (file);
1272         lf_printf (file, "#if defined(IS_FP_AVAILABLE)\n");
1273         lf_printf (file, "/* Validate: FP available according to cpu */\n");
1274         lf_printf (file, "if (!IS_FP_AVAILABLE) {\n");
1275         lf_indent (file, +2);
1276         print_idecode_invalid (file, "return",  invalid_fp_unavailable);
1277         lf_indent (file, -2);
1278         lf_printf (file, "}\n");
1279         lf_indent_suppress (file);
1280         lf_printf (file, "#endif\n");
1281       }
1282   }
1283   
1284   /* Validate: Validate Instruction in correct slot
1285
1286      Some architectures place restrictions on the slot that an
1287      instruction can be issued in */
1288
1289   {
1290     if (filter_is_member (instruction->options, "s")
1291         || options.gen.slot_verification)
1292       {
1293         lf_printf (file, "\n");
1294         lf_indent_suppress (file);
1295         lf_printf (file, "#if defined(IS_WRONG_SLOT)\n");
1296         lf_printf (file, "/* Validate: Instruction issued in correct slot */\n");
1297         lf_printf (file, "if (IS_WRONG_SLOT) {\n");
1298         lf_indent (file, +2);
1299         print_idecode_invalid (file, "return", invalid_wrong_slot);
1300         lf_indent (file, -2);
1301         lf_printf (file, "}\n");
1302         lf_indent_suppress (file);
1303         lf_printf (file, "#endif\n");
1304       }
1305   }
1306   
1307 }
1308
1309
1310 /****************************************************************/
1311
1312
1313 void
1314 print_idecode_issue_function_header (lf *file,
1315                                      const char *processor,
1316                                      function_decl_type decl_type,
1317                                      int nr_prefetched_words)
1318 {
1319   int indent;
1320   lf_printf (file, "\n");
1321   switch (decl_type)
1322     {
1323     case is_function_declaration:
1324       lf_print__function_type_function (file, print_semantic_function_type,
1325                                         "INLINE_IDECODE",
1326                                         " ");
1327       break;
1328     case is_function_definition:
1329       lf_print__function_type_function (file, print_semantic_function_type,
1330                                         "INLINE_IDECODE",
1331                                         "\n");
1332       break;
1333     case is_function_variable:
1334       print_semantic_function_type (file);
1335       lf_printf (file, " (*");
1336       break;
1337     }
1338   indent = print_function_name (file,
1339                                 "issue",
1340                                 NULL,
1341                                 processor,
1342                                 NULL,
1343                                 function_name_prefix_idecode);
1344   switch (decl_type)
1345     {
1346     case is_function_definition:
1347       indent += lf_printf (file, " (");
1348       break;
1349     case is_function_declaration:
1350       lf_putstr (file, "\n(");
1351       indent = 1;
1352       break;
1353     case is_function_variable:
1354       lf_putstr (file, ")\n(");
1355       indent = 1;
1356       break;
1357     }
1358   lf_indent (file, +indent);
1359   print_semantic_function_formal (file, nr_prefetched_words);
1360   lf_putstr (file, ")");
1361   lf_indent (file, -indent);
1362   switch (decl_type)
1363     {
1364     case is_function_definition:
1365       lf_printf (file, "\n");
1366       break;
1367     case is_function_declaration:
1368     case is_function_variable:
1369       lf_putstr (file, ";\n");
1370       break;
1371     }
1372 }
1373
1374
1375
1376 void
1377 print_idecode_globals (lf *file)
1378 {
1379   lf_printf (file, "enum {\n");
1380   lf_printf (file, "  /* greater or equal to zero => table */\n");
1381   lf_printf (file, "  function_entry = -1,\n");
1382   lf_printf (file, "  boolean_entry = -2,\n");
1383   lf_printf (file, "};\n");
1384   lf_printf (file, "\n");
1385   lf_printf (file, "typedef struct _idecode_table_entry {\n");
1386   lf_printf (file, "  int shift;\n");
1387   lf_printf (file, "  unsigned%d mask;\n", options.insn_bit_size);
1388   lf_printf (file, "  unsigned%d value;\n", options.insn_bit_size);
1389   lf_printf (file, "  void *function_or_table;\n");
1390   lf_printf (file, "} idecode_table_entry;\n");
1391 }