PowerPC64 ld segfault with code in non-executable sections
[external/binutils.git] / sim / ppc / gen-idecode.c
1 /*  This file is part of the program psim.
2
3     Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
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 3 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, see <http://www.gnu.org/licenses/>.
17  
18     */
19
20 #include "misc.h"
21 #include "lf.h"
22 #include "table.h"
23
24 #include "filter.h"
25
26 #include "ld-decode.h"
27 #include "ld-cache.h"
28 #include "ld-insn.h"
29
30 #include "igen.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                  insn_table *table)
41 {
42   if (table != NULL) {
43     while (1) {
44       ASSERT(table->opcode != NULL);
45       lf_printf(file, "_%d_%d",
46                 table->opcode->first,
47                 table->opcode->last);
48       if (table->parent == NULL) break;
49       lf_printf(file, "__%d", table->opcode_nr);
50       table = table->parent;
51     }
52   }
53 }
54
55 /****************************************************************/
56
57
58 static void
59 lf_print_table_name(lf *file,
60                     insn_table *table)
61 {
62   lf_printf(file, "idecode_table");
63   lf_print_opcodes(file, table);
64 }
65
66
67
68 static void
69 print_idecode_table(lf *file,
70                     insn_table *entry,
71                     const char *result)
72 {
73   lf_printf(file, "/* prime the search */\n");
74   lf_printf(file, "idecode_table_entry *table = ");
75   lf_print_table_name(file, entry);
76   lf_printf(file, ";\n");
77   lf_printf(file, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
78             i2target(hi_bit_nr, entry->opcode->first),
79             i2target(hi_bit_nr, entry->opcode->last));
80   lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
81
82   lf_printf(file, "\n");
83   lf_printf(file, "/* iterate until a leaf */\n");
84   lf_printf(file, "while (1) {\n");
85   lf_printf(file, "  signed shift = table_entry->shift;\n");
86   lf_printf(file, "if (shift == function_entry) break;\n");
87   lf_printf(file, "  if (shift >= 0) {\n");
88   lf_printf(file, "    table = ((idecode_table_entry*)\n");
89   lf_printf(file, "             table_entry->function_or_table);\n");
90   lf_printf(file, "    opcode = ((instruction & table_entry->mask)\n");
91   lf_printf(file, "              >> shift);\n");
92   lf_printf(file, "    table_entry = table + opcode;\n");
93   lf_printf(file, "  }\n");
94   lf_printf(file, "  else {\n");
95   lf_printf(file, "    /* must be a boolean */\n");
96   lf_printf(file, "    ASSERT(table_entry->shift == boolean_entry);\n");
97   lf_printf(file, "    opcode = ((instruction & table_entry->mask)\n");
98   lf_printf(file, "              != table_entry->value);\n");
99   lf_printf(file, "    table = ((idecode_table_entry*)\n");
100   lf_printf(file, "             table_entry->function_or_table);\n");
101   lf_printf(file, "    table_entry = table + opcode;\n");
102   lf_printf(file, "  }\n");
103   lf_printf(file, "}\n");
104
105   lf_printf(file, "\n");
106   lf_printf(file, "/* call the leaf code */\n");
107   if ((code & generate_jumps)) {
108     lf_printf(file, "goto *table_entry->function_or_table;\n");
109   }
110   else {
111     lf_printf(file, "%s ", result);
112     if ((code & generate_with_icache)) {
113       lf_printf(file, "(((idecode_icache*)table_entry->function_or_table)\n");
114       lf_printf(file, "  (%s));\n", ICACHE_FUNCTION_ACTUAL);
115     }
116     else {
117       lf_printf(file, "((idecode_semantic*)table_entry->function_or_table)\n");
118       lf_printf(file, "  (%s);\n", SEMANTIC_FUNCTION_ACTUAL);
119     }
120   }
121 }
122
123
124 static void
125 print_idecode_table_start(insn_table *table,
126                           lf *file,
127                           void *data,
128                           int depth)
129 {
130   ASSERT(depth == 0);
131   /* start of the table */
132   if (table->opcode_rule->gen == array_gen) {
133     lf_printf(file, "\n");
134     lf_printf(file, "static idecode_table_entry ");
135     lf_print_table_name(file, table);
136     lf_printf(file, "[] = {\n");
137   }
138 }
139
140 static void
141 print_idecode_table_leaf(insn_table *entry,
142                          lf *file,
143                          void *data,
144                          insn *instruction,
145                          int depth)
146 {
147   ASSERT(entry->parent != NULL);
148   ASSERT(depth == 0);
149
150   /* add an entry to the table */
151   if (entry->parent->opcode_rule->gen == array_gen) {
152     lf_printf(file, "  /*%d*/ { ", entry->opcode_nr);
153     if (entry->opcode == NULL) {
154       /* table leaf entry */
155       lf_printf(file, "function_entry, 0, 0, ");
156       if ((code & generate_jumps))
157         lf_printf(file, "&&");
158       print_function_name(file,
159                           entry->insns->file_entry->fields[insn_name],
160                           entry->expanded_bits,
161                           ((code & generate_with_icache)
162                            ? function_name_prefix_icache
163                            : function_name_prefix_semantics));
164     }
165     else if (entry->opcode_rule->gen == switch_gen
166              || entry->opcode_rule->gen == goto_switch_gen
167              || entry->opcode_rule->gen == padded_switch_gen) {
168       /* table calling switch statement */
169       lf_printf(file, "function_entry, 0, 0, ");
170       if ((code & generate_jumps))
171         lf_printf(file, "&&");
172       lf_print_table_name(file, entry);
173     }
174     else if (entry->opcode->is_boolean) {
175       /* table `calling' boolean table */
176       lf_printf(file, "boolean_entry, ");
177       lf_printf(file, "MASK32(%d, %d), ",
178                 i2target(hi_bit_nr, entry->opcode->first),
179                 i2target(hi_bit_nr, entry->opcode->last));
180       lf_printf(file, "INSERTED32(%d, %d, %d), ",
181                 entry->opcode->boolean_constant,
182                 i2target(hi_bit_nr, entry->opcode->first),
183                 i2target(hi_bit_nr, entry->opcode->last));
184       lf_print_table_name(file, entry);
185     }
186     else {
187       /* table `calling' another table */
188       lf_printf(file, "%d, ", insn_bit_size - entry->opcode->last - 1);
189       lf_printf(file, "MASK32(%d,%d), ",
190                 i2target(hi_bit_nr, entry->opcode->first),
191                 i2target(hi_bit_nr, entry->opcode->last));
192       lf_printf(file, "0, ");
193       lf_print_table_name(file, entry);
194     }
195     lf_printf(file, " },\n");
196   }
197 }
198
199 static void
200 print_idecode_table_end(insn_table *table,
201                         lf *file,
202                         void *data,
203                         int depth)
204 {
205   ASSERT(depth == 0);
206   if (table->opcode_rule->gen == array_gen) {
207     lf_printf(file, "};\n");
208   }
209 }
210
211 static void
212 print_idecode_table_padding(insn_table *table,
213                             lf *file,
214                             void *data,
215                             int depth,
216                             int opcode_nr)
217 {
218   ASSERT(depth == 0);
219   if (table->opcode_rule->gen == array_gen) {
220     lf_printf(file, "  /*%d*/ { function_entry, 0, 0, ", opcode_nr);
221     if ((code & generate_jumps))
222       lf_printf(file, "&&");
223     lf_printf(file, "%s_illegal },\n",
224               ((code & generate_with_icache) ? "icache" : "semantic"));
225   }
226 }
227
228
229 /****************************************************************/
230
231
232 static void
233 print_goto_switch_name(lf *file,
234                        insn_table *entry)
235 {
236   lf_printf(file, "case_");
237   if (entry->opcode == NULL)
238     print_function_name(file,
239                         entry->insns->file_entry->fields[insn_name],
240                         entry->expanded_bits,
241                         ((code & generate_with_icache)
242                          ? function_name_prefix_icache
243                          : function_name_prefix_semantics));
244   else
245     lf_print_table_name(file, entry);
246 }
247
248 static void
249 print_goto_switch_table_leaf(insn_table *entry,
250                              lf *file,
251                              void *data,
252                              insn *instruction,
253                              int depth)
254 {
255   ASSERT(entry->parent != NULL);
256   ASSERT(depth == 0);
257   ASSERT(entry->parent->opcode_rule->gen == goto_switch_gen);
258   ASSERT(entry->parent->opcode);
259
260   lf_printf(file, "&&");
261   print_goto_switch_name(file, entry);
262   lf_printf(file, ",\n");
263 }
264
265 static void
266 print_goto_switch_table_padding(insn_table *table,
267                                 lf *file,
268                                 void *data,
269                                 int depth,
270                                 int opcode_nr)
271 {
272   ASSERT(depth == 0);
273   ASSERT(table->opcode_rule->gen == goto_switch_gen);
274
275   lf_printf(file, "&&illegal_");
276   lf_print_table_name(file, table);
277   lf_printf(file, ",\n");
278 }
279
280 static void
281 print_goto_switch_break(lf *file,
282                         insn_table *entry)
283 {
284   lf_printf(file, "goto break_");
285   lf_print_table_name(file, entry->parent);
286   lf_printf(file, ";\n");
287 }
288
289
290 static void
291 print_goto_switch_table(lf *file,
292                         insn_table *table)
293 {
294   lf_printf(file, "const static void *");
295   lf_print_table_name(file, table);
296   lf_printf(file, "[] = {\n");
297   lf_indent(file, +2);
298   insn_table_traverse_tree(table,
299                            file, NULL/*data*/,
300                            0,
301                            NULL/*start*/,
302                            print_goto_switch_table_leaf,
303                            NULL/*end*/,
304                            print_goto_switch_table_padding);
305   lf_indent(file, -2);
306   lf_printf(file, "};\n");
307 }
308
309
310 void print_idecode_switch
311 (lf *file, 
312  insn_table *table,
313  const char *result);
314
315 static void
316 idecode_switch_start(insn_table *table,
317                      lf *file,
318                      void *data,
319                      int depth)
320 {
321   /* const char *result = data; */
322   ASSERT(depth == 0);
323   ASSERT(table->opcode_rule->gen == switch_gen
324          || table->opcode_rule->gen == goto_switch_gen
325          || table->opcode_rule->gen == padded_switch_gen);
326
327   if (table->opcode->is_boolean
328       || table->opcode_rule->gen == switch_gen
329          || table->opcode_rule->gen == padded_switch_gen) {
330     lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
331               i2target(hi_bit_nr, table->opcode->first),
332               i2target(hi_bit_nr, table->opcode->last));
333   }
334   else if (table->opcode_rule->gen == goto_switch_gen) {
335     if (table->parent != NULL
336         && (table->parent->opcode_rule->gen == switch_gen
337             || table->parent->opcode_rule->gen == goto_switch_gen
338             || table->parent->opcode_rule->gen == padded_switch_gen)) {
339       lf_printf(file, "{\n");
340       lf_indent(file, +2);
341     }
342     print_goto_switch_table(file, table);
343     lf_printf(file, "ASSERT(EXTRACTED32(instruction, %d, %d)\n",
344               i2target(hi_bit_nr, table->opcode->first),
345               i2target(hi_bit_nr, table->opcode->last));
346     lf_printf(file, "       < (sizeof(");
347     lf_print_table_name(file, table);
348     lf_printf(file, ") / sizeof(void*)));\n");
349     lf_printf(file, "goto *");
350     lf_print_table_name(file, table);
351     lf_printf(file, "[EXTRACTED32(instruction, %d, %d)];\n",
352               i2target(hi_bit_nr, table->opcode->first),
353               i2target(hi_bit_nr, table->opcode->last));
354   }
355   else {
356     ASSERT("bad switch" == NULL);
357   }
358 }
359
360
361 static void
362 idecode_switch_leaf(insn_table *entry,
363                     lf *file,
364                     void *data,
365                     insn *instruction,
366                     int depth)
367 {
368   const char *result = data;
369   ASSERT(entry->parent != NULL);
370   ASSERT(depth == 0);
371   ASSERT(entry->parent->opcode_rule->gen == switch_gen
372          || entry->parent->opcode_rule->gen == goto_switch_gen
373          || entry->parent->opcode_rule->gen == padded_switch_gen);
374   ASSERT(entry->parent->opcode);
375
376   if (entry->parent->opcode->is_boolean
377       && entry->opcode_nr == 0) {
378     /* boolean false target */
379     lf_printf(file, "case %d:\n", entry->parent->opcode->boolean_constant);
380   }
381   else if (entry->parent->opcode->is_boolean
382            && entry->opcode_nr != 0) {
383     /* boolean true case */
384     lf_printf(file, "default:\n");
385   }
386   else if (entry->parent->opcode_rule->gen == switch_gen
387            || entry->parent->opcode_rule->gen == padded_switch_gen) {
388     /* normal goto */
389     lf_printf(file, "case %d:\n", entry->opcode_nr);
390   }
391   else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
392     /* lf_indent(file, -1); */
393     print_goto_switch_name(file, entry);
394     lf_printf(file, ":\n");
395     /* lf_indent(file, +1); */
396   }
397   else {
398     ASSERT("bad switch" == NULL);
399   }
400   lf_indent(file, +2);
401   {
402     if (entry->opcode == NULL) {
403       /* switch calling leaf */
404       if ((code & generate_jumps))
405         lf_printf(file, "goto ");
406       if ((code & generate_calls))
407         lf_printf(file, "%s ", result);
408       print_function_name(file,
409                           entry->insns->file_entry->fields[insn_name],
410                           entry->expanded_bits,
411                           ((code & generate_with_icache)
412                            ? function_name_prefix_icache
413                            : function_name_prefix_semantics));
414       if ((code & generate_calls))
415         lf_printf(file, "(%s)", SEMANTIC_FUNCTION_ACTUAL);
416       lf_printf(file, ";\n");
417     }
418     else if (entry->opcode_rule->gen == switch_gen
419              || entry->opcode_rule->gen == goto_switch_gen
420              || entry->opcode_rule->gen == padded_switch_gen) {
421       /* switch calling switch */
422       print_idecode_switch(file, entry, result);
423     }
424     else {
425       /* switch looking up a table */
426       lf_printf(file, "{\n");
427       lf_indent(file, -2);
428       print_idecode_table(file, entry, result);
429       lf_indent(file, -2);
430       lf_printf(file, "}\n");
431     }
432     if (entry->parent->opcode->is_boolean
433         || entry->parent->opcode_rule->gen == switch_gen
434         || entry->parent->opcode_rule->gen == padded_switch_gen) {
435       lf_printf(file, "break;\n");
436     }
437     else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
438       print_goto_switch_break(file, entry);
439     }
440     else {
441       ASSERT("bad switch" == NULL);
442     }
443   }
444   lf_indent(file, -2);
445 }
446
447
448 static void
449 print_idecode_switch_illegal(lf *file,
450                              const char *result)
451 {
452   lf_indent(file, +2);
453   print_idecode_illegal(file, result);
454   lf_printf(file, "break;\n");
455   lf_indent(file, -2);
456 }
457
458 static void
459 idecode_switch_end(insn_table *table,
460                    lf *file,
461                    void *data,
462                    int depth)
463 {
464   const char *result = data;
465   ASSERT(depth == 0);
466   ASSERT(table->opcode_rule->gen == switch_gen
467          || table->opcode_rule->gen == goto_switch_gen
468          || table->opcode_rule->gen == padded_switch_gen);
469   ASSERT(table->opcode);
470
471   if (table->opcode->is_boolean) {
472     lf_printf(file, "}\n");
473   }
474   else if (table->opcode_rule->gen == switch_gen
475            || table->opcode_rule->gen == padded_switch_gen) {
476     lf_printf(file, "default:\n");
477     switch (table->opcode_rule->gen) {
478     case switch_gen:
479       print_idecode_switch_illegal(file, result);
480       break;
481     case padded_switch_gen:
482       lf_printf(file, "  error(\"Internal error - bad switch generated\\n\");\n");
483       lf_printf(file, "  break;\n");
484       break;
485     default:
486       ASSERT("bad switch" == NULL);
487     }
488     lf_printf(file, "}\n");
489   }
490   else if (table->opcode_rule->gen == goto_switch_gen) {
491     lf_printf(file, "illegal_");
492     lf_print_table_name(file, table);
493     lf_printf(file, ":\n");
494     print_idecode_illegal(file, result);
495     lf_printf(file, "break_");
496     lf_print_table_name(file, table);
497     lf_printf(file, ":;\n");
498     if (table->parent != NULL
499         && (table->parent->opcode_rule->gen == switch_gen
500             || table->parent->opcode_rule->gen == goto_switch_gen
501             || table->parent->opcode_rule->gen == padded_switch_gen)) {
502       lf_indent(file, -2);
503       lf_printf(file, "}\n");
504     }
505   }
506   else {
507     ASSERT("bad switch" == NULL);
508   }
509 }
510
511 static void
512 idecode_switch_padding(insn_table *table,
513                        lf *file,
514                        void *data,
515                        int depth,
516                        int opcode_nr)
517 {
518   const char *result = data;
519   ASSERT(depth == 0);
520   ASSERT(table->opcode_rule->gen == switch_gen
521          || table->opcode_rule->gen == goto_switch_gen
522          || table->opcode_rule->gen == padded_switch_gen);
523
524   switch (table->opcode_rule->gen) {
525   case switch_gen:
526     break;
527   case padded_switch_gen:
528     lf_printf(file, "case %d:\n", opcode_nr);
529     print_idecode_switch_illegal(file, result);
530     break;
531   case goto_switch_gen:
532     /* no padding needed */
533     break;
534   default:
535     ASSERT("bad switch" != NULL);
536   }
537 }
538
539
540 void
541 print_idecode_switch(lf *file, 
542                      insn_table *table,
543                      const char *result)
544 {
545   insn_table_traverse_tree(table,
546                            file, (void*)result,
547                            0,
548                            idecode_switch_start,
549                            idecode_switch_leaf,
550                            idecode_switch_end,
551                            idecode_switch_padding);
552 }
553
554
555 static void
556 print_idecode_switch_function_header(lf *file,
557                                      insn_table *table,
558                                      int is_function_definition)
559 {
560   lf_printf(file, "\n");
561   if ((code & generate_calls)) {
562     lf_printf(file, "static ");
563     if ((code & generate_with_icache))
564       lf_printf(file, "idecode_semantic *");
565     else
566       lf_printf(file, "unsigned_word");
567     if (is_function_definition)
568       lf_printf(file, "\n");
569     else
570       lf_printf(file, " ");
571     lf_print_table_name(file, table);
572     lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
573     if (!is_function_definition)
574       lf_printf(file, ";");
575     lf_printf(file, "\n");
576   }
577   if ((code & generate_jumps) && is_function_definition) {
578     lf_indent(file, -1);
579     lf_print_table_name(file, table);
580     lf_printf(file, ":\n");
581     lf_indent(file, +1);
582   }
583 }
584
585
586 static void
587 idecode_declare_if_switch(insn_table *table,
588                           lf *file,
589                           void *data,
590                           int depth)
591 {
592   if ((table->opcode_rule->gen == switch_gen
593        || table->opcode_rule->gen == goto_switch_gen
594        || table->opcode_rule->gen == padded_switch_gen)
595       && table->parent != NULL /* don't declare the top one yet */
596       && table->parent->opcode_rule->gen == array_gen) {
597     print_idecode_switch_function_header(file,
598                                          table,
599                                          0/*isnt function definition*/);
600   }
601 }
602
603
604 static void
605 idecode_expand_if_switch(insn_table *table,
606                          lf *file,
607                          void *data,
608                          int depth)
609 {
610   if ((table->opcode_rule->gen == switch_gen
611        || table->opcode_rule->gen == goto_switch_gen
612        || table->opcode_rule->gen == padded_switch_gen)
613       && table->parent != NULL /* don't expand the top one yet */
614       && table->parent->opcode_rule->gen == array_gen) {
615     print_idecode_switch_function_header(file,
616                                             table,
617                                             1/*is function definition*/);
618     if ((code & generate_calls)) {
619       lf_printf(file, "{\n");
620       lf_indent(file, +2);
621     }
622     print_idecode_switch(file, table, "return");
623     if ((code & generate_calls)) {
624       lf_indent(file, -2);
625       lf_printf(file, "}\n");
626     }
627   }
628 }
629
630
631 /****************************************************************/
632
633
634 static void
635 print_idecode_lookups(lf *file,
636                       insn_table *table,
637                       cache_table *cache_rules)
638 {
639   int depth;
640
641   /* output switch function declarations where needed by tables */
642   insn_table_traverse_tree(table,
643                            file, NULL,
644                            1,
645                            idecode_declare_if_switch, /* START */
646                            NULL, NULL, NULL);
647   
648   /* output tables where needed */
649   for (depth = insn_table_depth(table);
650        depth > 0;
651        depth--) {
652     insn_table_traverse_tree(table,
653                              file, NULL,
654                              1-depth,
655                              print_idecode_table_start,
656                              print_idecode_table_leaf,
657                              print_idecode_table_end,
658                              print_idecode_table_padding);
659   }
660   
661   /* output switch functions where needed */
662   insn_table_traverse_tree(table,
663                            file, NULL,
664                            1,
665                            idecode_expand_if_switch, /* START */
666                            NULL, NULL, NULL);
667 }
668
669
670 static void
671 print_idecode_body(lf *file,
672                    insn_table *table,
673                    const char *result)
674 {
675   if (table->opcode_rule->gen == switch_gen
676       || table->opcode_rule->gen == goto_switch_gen
677       || table->opcode_rule->gen == padded_switch_gen)
678     print_idecode_switch(file, table, result);
679   else
680     print_idecode_table(file, table, result);
681 }
682
683
684 /****************************************************************/
685
686
687 static void
688 print_run_until_stop_body(lf *file,
689                           insn_table *table,
690                           int can_stop)
691 {
692   /* Output the function to execute real code:
693
694      Unfortunatly, there are multiple cases to consider vis:
695
696      <icache> X <smp> X <events> X <keep-running-flag> X ...
697
698      Consequently this function is written in multiple different ways */
699
700   lf_putstr(file, "{\n");
701   lf_indent(file, +2);
702   lf_putstr(file, "jmp_buf halt;\n");
703   lf_putstr(file, "jmp_buf restart;\n");
704   if (!generate_smp) {
705     lf_putstr(file, "cpu *processor = NULL;\n");
706     lf_putstr(file, "unsigned_word cia = -1;\n");
707   }
708   lf_putstr(file, "int last_cpu;\n");
709   if (generate_smp) {
710     lf_putstr(file, "int current_cpu;\n");
711   }
712
713   if ((code & generate_with_icache)) {
714     lf_putstr(file, "int cpu_nr;\n");
715     lf_putstr(file, "\n");
716     lf_putstr(file, "/* flush the icache of a possible break insn */\n");
717     lf_putstr(file, "for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
718     lf_putstr(file, "  cpu_flush_icache(processors[cpu_nr]);\n");
719   }
720
721   lf_putstr(file, "\n");
722   lf_putstr(file, "/* set the halt target initially */\n");
723   lf_putstr(file, "psim_set_halt_and_restart(system, &halt, NULL);\n");
724   lf_putstr(file, "if (setjmp(halt))\n");
725   lf_putstr(file, "  return;\n");
726
727   lf_putstr(file, "\n");
728   lf_putstr(file, "/* where were we before the halt? */\n");
729   lf_putstr(file, "last_cpu = psim_last_cpu(system);\n");
730
731   lf_putstr(file, "\n");
732   lf_putstr(file, "/* check for need to force event processing first */\n");
733   lf_putstr(file, "if (WITH_EVENTS) {\n");
734   lf_putstr(file, "  if (last_cpu == nr_cpus) {\n");
735   lf_putstr(file, "    /* halted during event processing */\n");
736   lf_putstr(file, "    event_queue_process(events);\n");
737   lf_putstr(file, "    last_cpu = -1;\n");
738   lf_putstr(file, "  }\n");
739   lf_putstr(file, "  else if (last_cpu == nr_cpus - 1) {\n");
740   lf_putstr(file, "    /* last cpu did halt */\n");
741   lf_putstr(file, "    if (event_queue_tick(events)) {\n");
742   lf_putstr(file, "      event_queue_process(events);\n");
743   lf_putstr(file, "    }\n");
744   lf_putstr(file, "    last_cpu = -1;\n");
745   lf_putstr(file, "  }\n");
746   lf_putstr(file, "}\n");
747   lf_putstr(file, "else {\n");
748   lf_putstr(file, " if (last_cpu == nr_cpus - 1)\n");
749   lf_putstr(file, "   /* cpu zero is next */\n");
750   lf_putstr(file, "   last_cpu = -1;\n");
751   lf_putstr(file, "}\n");
752
753   lf_putstr(file, "\n");
754   lf_putstr(file, "/* have ensured that the event queue can not be first */\n");
755   lf_putstr(file, "ASSERT(last_cpu >= -1 && last_cpu < nr_cpus - 1);\n");
756
757   if (!generate_smp) {
758
759     lf_putstr(file, "\n\
760 /* CASE 1: NO SMP (with or with out instruction cache).\n\
761 \n\
762    In this case, we can take advantage of the fact that the current\n\
763    instruction address does not need to be returned to the cpu object\n\
764    after every execution of an instruction.  Instead it only needs to\n\
765    be saved when either A. the main loop exits or B. A cpu-halt or\n\
766    cpu-restart call forces the loop to be re-enered.  The later\n\
767    functions always save the current cpu instruction address.\n\
768 \n\
769    Two subcases also exist that with and that without an instruction\n\
770    cache.\n\
771 \n\
772    An additional complexity is the need to ensure that a 1:1 ratio\n\
773    is maintained between the execution of an instruction and the\n\
774    incrementing of the simulation clock */");
775
776     lf_putstr(file, "\n");
777
778     lf_putstr(file, "\n");
779     lf_putstr(file, "/* now add restart target as ready to run */\n");
780     lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
781     lf_putstr(file, "if (setjmp(restart)) {\n");
782     lf_putstr(file, "  if (WITH_EVENTS) {\n");
783     lf_putstr(file, "    /* when restart, cpu must have been last, clock next */\n");
784     lf_putstr(file, "    if (event_queue_tick(events)) {\n");
785     lf_putstr(file, "      event_queue_process(events);\n");
786     lf_putstr(file, "    }\n");
787     lf_putstr(file, "  }\n");
788     lf_putstr(file, "}\n");
789
790     lf_putstr(file, "\n");
791     lf_putstr(file, "/* prime the main loop */\n");
792     lf_putstr(file, "processor = processors[0];\n");
793     lf_putstr(file, "cia = cpu_get_program_counter(processor);\n");
794
795     lf_putstr(file, "\n");
796     lf_putstr(file, "while (1) {\n");
797     lf_indent(file, +2);
798
799     if (!(code & generate_with_icache)) {
800       lf_putstr(file, "instruction_word instruction =\n");
801       lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
802       lf_putstr(file, "\n");
803       print_idecode_body(file, table, "cia =");;
804     }
805
806     if ((code & generate_with_icache)) {
807       lf_putstr(file, "idecode_cache *cache_entry =\n");
808       lf_putstr(file, "  cpu_icache_entry(processor, cia);\n");
809       lf_putstr(file, "if (cache_entry->address == cia) {\n");
810       lf_putstr(file, "  /* cache hit */\n");
811       lf_putstr(file, "  idecode_semantic *const semantic = cache_entry->semantic;\n");
812       lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
813       /* tail */
814       if (can_stop) {
815         lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
816         lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
817       }
818       lf_putstr(file, "}\n");
819       lf_putstr(file, "else {\n");
820       lf_putstr(file, "  /* cache miss */\n");
821       if (!(code & generate_with_semantic_icache)) {
822         lf_indent(file, +2);
823         lf_putstr(file, "idecode_semantic *semantic;\n");
824         lf_indent(file, -2);
825       }
826       lf_putstr(file, "  instruction_word instruction =\n");
827       lf_putstr(file, "    vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
828       lf_putstr(file, "  if (WITH_MON != 0)\n");
829       lf_putstr(file, "    mon_event(mon_event_icache_miss, processor, cia);\n");
830       if ((code & generate_with_semantic_icache)) {
831         lf_putstr(file, "{\n");
832         lf_indent(file, +2);
833         print_idecode_body(file, table, "cia =");
834         lf_indent(file, -2);
835         lf_putstr(file, "}\n");
836       }
837       else {
838         print_idecode_body(file, table, "semantic =");
839         lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
840       }
841       lf_putstr(file, "}\n");
842     }
843
844     /* events */
845     lf_putstr(file, "\n");
846     lf_putstr(file, "/* process any events */\n");
847     lf_putstr(file, "if (WITH_EVENTS) {\n");
848     lf_putstr(file, "  if (event_queue_tick(events)) {\n");
849     lf_putstr(file, "    cpu_set_program_counter(processor, cia);\n");
850     lf_putstr(file, "    event_queue_process(events);\n");
851     lf_putstr(file, "    cia = cpu_get_program_counter(processor);\n");
852     lf_putstr(file, "  }\n");
853     lf_putstr(file, "}\n");
854
855     /* tail */
856     if (can_stop) {
857       lf_putstr(file, "\n");
858       lf_putstr(file, "/* abort if necessary */\n");
859       lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
860       lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*not important*/);\n");
861     }
862
863     lf_indent(file, -2);
864     lf_putstr(file, "}\n");
865   }
866     
867   if (generate_smp) {
868
869     lf_putstr(file, "\n\
870 /* CASE 2: SMP (With or without ICACHE)\n\
871 \n\
872    The complexity here comes from needing to correctly restart the\n\
873    system when it is aborted.  In particular if cpu0 requests a\n\
874    restart, the next cpu is still cpu1.  Cpu0 being restarted after\n\
875    all the other CPU's and the event queue have been processed */");
876
877     lf_putstr(file, "\n");
878
879     lf_putstr(file, "\n");
880     lf_putstr(file, "/* now establish the restart target */\n");
881     lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
882     lf_putstr(file, "if (setjmp(restart)) {\n");
883     lf_putstr(file, "  current_cpu = psim_last_cpu(system);\n");
884     lf_putstr(file, "  ASSERT(current_cpu >= 0 && current_cpu < nr_cpus);\n");
885     lf_putstr(file, "}\n");
886     lf_putstr(file, "else {\n");
887     lf_putstr(file, "  current_cpu = last_cpu;\n");
888     lf_putstr(file, "  ASSERT(current_cpu >= -1 && current_cpu < nr_cpus);\n");
889     lf_putstr(file, "}\n");
890     
891
892     lf_putstr(file, "\n");
893     lf_putstr(file, "while (1) {\n");
894     lf_indent(file, +2);
895
896     lf_putstr(file, "\n");
897     lf_putstr(file, "if (WITH_EVENTS) {\n");
898     lf_putstr(file, "  current_cpu += 1;\n");
899     lf_putstr(file, "  if (current_cpu == nr_cpus) {\n");
900     lf_putstr(file, "    if (event_queue_tick(events)) {\n");
901     lf_putstr(file, "      event_queue_process(events);\n");
902     lf_putstr(file, "    }\n");
903     lf_putstr(file, "    current_cpu = 0;\n");
904     lf_putstr(file, "  }\n");
905     lf_putstr(file, "}\n");
906     lf_putstr(file, "else {\n");
907     lf_putstr(file, "  current_cpu = (current_cpu + 1) % nr_cpus;\n");
908     lf_putstr(file, "}\n");
909
910     lf_putstr(file, "\n");
911     lf_putstr(file, "{\n");
912     lf_indent(file, +2);
913     lf_putstr(file, "cpu *processor = processors[current_cpu];\n");
914     lf_putstr(file, "unsigned_word cia =\n");
915     lf_putstr(file, "  cpu_get_program_counter(processor);\n");
916
917     if (!(code & generate_with_icache)) {
918       lf_putstr(file, "instruction_word instruction =\n");
919       lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
920       print_idecode_body(file, table, "cia =");
921       if (can_stop) {
922         lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
923         lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
924       }
925       lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
926     }
927
928     if ((code & generate_with_icache)) {
929       lf_putstr(file, "idecode_cache *cache_entry =\n");
930       lf_putstr(file, "  cpu_icache_entry(processor, cia);\n");
931       lf_putstr(file, "\n");
932       lf_putstr(file, "if (cache_entry->address == cia) {\n");
933       {
934         lf_indent(file, +2);
935         lf_putstr(file, "\n");
936         lf_putstr(file, "/* cache hit */\n");
937         lf_putstr(file, "idecode_semantic *semantic = cache_entry->semantic;\n");
938         lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
939         /* tail */
940         if (can_stop) {
941           lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
942           lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
943         }
944         lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
945         lf_putstr(file, "\n");
946         lf_indent(file, -2);
947       }
948       lf_putstr(file, "}\n");
949       lf_putstr(file, "else {\n");
950       {
951         lf_indent(file, +2);
952         lf_putstr(file, "\n");
953         lf_putstr(file, "/* cache miss */\n");
954         if (!(code & generate_with_semantic_icache)) {
955           lf_putstr(file, "idecode_semantic *semantic;\n");
956         }
957         lf_putstr(file, "instruction_word instruction =\n");
958         lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
959         lf_putstr(file, "if (WITH_MON != 0)\n");
960         lf_putstr(file, "  mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
961         if ((code & generate_with_semantic_icache)) {
962           lf_putstr(file, "{\n");
963           lf_indent(file, +2);
964           print_idecode_body(file, table, "cia =");
965           lf_indent(file, -2);
966           lf_putstr(file, "}\n");
967         }
968         else {
969           print_idecode_body(file, table, "semantic = ");
970           lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
971         }
972         /* tail */
973         if (can_stop) {
974           lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
975           lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
976         }
977         lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
978         lf_putstr(file, "\n");
979         lf_indent(file, -2);
980       }
981       lf_putstr(file, "}\n");
982     }
983
984     /* close */
985     lf_indent(file, -2);
986     lf_putstr(file, "}\n");
987
988     /* tail */
989     lf_indent(file, -2);
990     lf_putstr(file, "}\n");
991   }
992
993
994   lf_indent(file, -2);
995   lf_putstr(file, "}\n");
996 }
997
998
999 /****************************************************************/
1000
1001 static void
1002 print_jump(lf *file,
1003            int is_tail)
1004 {
1005   if (is_tail) {
1006     lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
1007     lf_putstr(file, "  cpu_halt(processor, nia, was_continuing, 0/*na*/);\n");
1008   }
1009   
1010   if (!generate_smp) {
1011     lf_putstr(file, "if (WITH_EVENTS) {\n");
1012     lf_putstr(file, "  if (event_queue_tick(events)) {\n");
1013     lf_putstr(file, "    cpu_set_program_counter(processor, nia);\n");
1014     lf_putstr(file, "    event_queue_process(events);\n");
1015     lf_putstr(file, "    nia = cpu_get_program_counter(processor);\n");
1016     lf_putstr(file, "  }\n");
1017     lf_putstr(file, "}\n");
1018   }
1019
1020   if (generate_smp) {
1021     if (is_tail)
1022       lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
1023     lf_putstr(file, "if (WITH_EVENTS) {\n");
1024     lf_putstr(file, "  current_cpu += 1;\n");
1025     lf_putstr(file, "  if (current_cpu >= nr_cpus) {\n");
1026     lf_putstr(file, "    if (event_queue_tick(events)) {\n");
1027     lf_putstr(file, "      event_queue_process(events);\n");
1028     lf_putstr(file, "    }\n");
1029     lf_putstr(file, "    current_cpu = 0;\n");
1030     lf_putstr(file, "  }\n");
1031     lf_putstr(file, "}\n");
1032     lf_putstr(file, "else {\n");
1033     lf_putstr(file, "  current_cpu = (current_cpu + 1) % nr_cpus;\n");
1034     lf_putstr(file, "}\n");
1035     lf_putstr(file, "processor = processors[current_cpu];\n");
1036     lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
1037   }
1038
1039   if ((code & generate_with_icache)) {
1040     lf_putstr(file, "cache_entry = cpu_icache_entry(processor, nia);\n");
1041     lf_putstr(file, "if (cache_entry->address == nia) {\n");
1042     lf_putstr(file, "  /* cache hit */\n");
1043     lf_putstr(file, "  goto *cache_entry->semantic;\n");
1044     lf_putstr(file, "}\n");
1045     if (is_tail) {
1046       lf_putstr(file, "goto cache_miss;\n");
1047     }
1048   }
1049
1050   if (!(code & generate_with_icache) && is_tail) {
1051     lf_printf(file, "goto idecode;\n");
1052   }
1053
1054 }
1055
1056
1057
1058
1059
1060 static void
1061 print_jump_insn(lf *file,
1062                 insn *instruction,
1063                 insn_bits *expanded_bits,
1064                 opcode_field *opcodes,
1065                 cache_table *cache_rules)
1066 {
1067
1068   /* what we are for the moment */
1069   lf_printf(file, "\n");
1070   print_my_defines(file, expanded_bits, instruction->file_entry);
1071
1072   /* output the icache entry */
1073   if ((code & generate_with_icache)) {
1074     lf_printf(file, "\n");
1075     lf_indent(file, -1);
1076     print_function_name(file,
1077                         instruction->file_entry->fields[insn_name],
1078                         expanded_bits,
1079                         function_name_prefix_icache);
1080     lf_printf(file, ":\n");
1081     lf_indent(file, +1);
1082     lf_printf(file, "{\n");
1083     lf_indent(file, +2);
1084     lf_putstr(file, "const unsigned_word cia = nia;\n");
1085     print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
1086     print_idecode_validate(file, instruction, opcodes);
1087     lf_printf(file, "\n");
1088     lf_printf(file, "{\n");
1089     lf_indent(file, +2);
1090     print_icache_body(file,
1091                       instruction,
1092                       expanded_bits,
1093                       cache_rules,
1094                       0, /*use_defines*/
1095                       put_values_in_icache);
1096     lf_printf(file, "cache_entry->address = nia;\n");
1097     lf_printf(file, "cache_entry->semantic = &&");
1098     print_function_name(file,
1099                         instruction->file_entry->fields[insn_name],
1100                         expanded_bits,
1101                         function_name_prefix_semantics);
1102     lf_printf(file, ";\n");
1103     if ((code & generate_with_semantic_icache)) {
1104       print_semantic_body(file,
1105                           instruction,
1106                           expanded_bits,
1107                           opcodes);
1108       print_jump(file, 1/*is-tail*/);
1109     }
1110     else {
1111       lf_printf(file, "/* goto ");
1112       print_function_name(file,
1113                           instruction->file_entry->fields[insn_name],
1114                           expanded_bits,
1115                           function_name_prefix_semantics);
1116       lf_printf(file, "; */\n");
1117     }
1118     lf_indent(file, -2);
1119     lf_putstr(file, "}\n");
1120     lf_indent(file, -2);
1121     lf_printf(file, "}\n");
1122   }
1123
1124   /* print the semantics */
1125   lf_printf(file, "\n");
1126   lf_indent(file, -1);
1127   print_function_name(file,
1128                       instruction->file_entry->fields[insn_name],
1129                       expanded_bits,
1130                       function_name_prefix_semantics);
1131   lf_printf(file, ":\n");
1132   lf_indent(file, +1);
1133   lf_printf(file, "{\n");
1134   lf_indent(file, +2);
1135   lf_putstr(file, "const unsigned_word cia = nia;\n");
1136   print_icache_body(file,
1137                     instruction,
1138                     expanded_bits,
1139                     cache_rules,
1140                     ((code & generate_with_direct_access)
1141                      ? define_variables
1142                      : declare_variables),
1143                     ((code & generate_with_icache)
1144                      ? get_values_from_icache
1145                      : do_not_use_icache));
1146   print_semantic_body(file,
1147                       instruction,
1148                       expanded_bits,
1149                       opcodes);
1150   if (code & generate_with_direct_access)
1151     print_icache_body(file,
1152                       instruction,
1153                       expanded_bits,
1154                       cache_rules,
1155                       undef_variables,
1156                       ((code & generate_with_icache)
1157                        ? get_values_from_icache
1158                        : do_not_use_icache));
1159   print_jump(file, 1/*is tail*/);
1160   lf_indent(file, -2);
1161   lf_printf(file, "}\n");
1162 }
1163
1164 static void
1165 print_jump_definition(insn_table *entry,
1166                       lf *file,
1167                       void *data,
1168                       insn *instruction,
1169                       int depth)
1170 {
1171   cache_table *cache_rules = (cache_table*)data;
1172   if (generate_expanded_instructions) {
1173     ASSERT(entry->nr_insn == 1
1174            && entry->opcode == NULL
1175            && entry->parent != NULL
1176            && entry->parent->opcode != NULL);
1177     ASSERT(entry->nr_insn == 1
1178            && entry->opcode == NULL
1179            && entry->parent != NULL
1180            && entry->parent->opcode != NULL
1181            && entry->parent->opcode_rule != NULL);
1182     print_jump_insn(file,
1183                     entry->insns,
1184                     entry->expanded_bits,
1185                     entry->opcode,
1186                     cache_rules);
1187   }
1188   else {
1189     print_jump_insn(file,
1190                     instruction,
1191                     NULL,
1192                     NULL,
1193                     cache_rules);
1194   }
1195 }
1196
1197
1198 static void
1199 print_jump_internal_function(insn_table *table,
1200                              lf *file,
1201                              void *data,
1202                              table_entry *function)
1203 {
1204   if (it_is("internal", function->fields[insn_flags])) {
1205     lf_printf(file, "\n");
1206     table_entry_print_cpp_line_nr(file, function);
1207     lf_indent(file, -1);
1208     print_function_name(file,
1209                         function->fields[insn_name],
1210                         NULL,
1211                         ((code & generate_with_icache)
1212                          ? function_name_prefix_icache
1213                          : function_name_prefix_semantics));
1214     lf_printf(file, ":\n");
1215     lf_indent(file, +1);
1216     lf_printf(file, "{\n");
1217     lf_indent(file, +2);
1218     lf_printf(file, "const unsigned_word cia = nia;\n");
1219     lf_print__c_code(file, function->annex);
1220     lf_print__internal_reference(file);
1221     lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
1222     lf_indent(file, -2);
1223     lf_printf(file, "}\n");
1224   }
1225 }
1226
1227 static void
1228 print_jump_until_stop_body(lf *file,
1229                            insn_table *table,
1230                            cache_table *cache_rules,
1231                            int can_stop)
1232 {
1233   lf_printf(file, "{\n");
1234   lf_indent(file, +2);
1235   if (!can_stop)
1236     lf_printf(file, "int *keep_running = NULL;\n");
1237   lf_putstr(file, "jmp_buf halt;\n");
1238   lf_putstr(file, "jmp_buf restart;\n");
1239   lf_putstr(file, "cpu *processor = NULL;\n");
1240   lf_putstr(file, "unsigned_word nia = -1;\n");
1241   lf_putstr(file, "instruction_word instruction = 0;\n");
1242   if ((code & generate_with_icache)) {
1243     lf_putstr(file, "idecode_cache *cache_entry = NULL;\n");
1244   }
1245   if (generate_smp) {
1246     lf_putstr(file, "int current_cpu = -1;\n");
1247   }
1248
1249   /* all the switches and tables - they know about jumping */
1250   print_idecode_lookups(file, table, cache_rules);
1251  
1252   /* start the simulation up */
1253   if ((code & generate_with_icache)) {
1254     lf_putstr(file, "\n");
1255     lf_putstr(file, "{\n");
1256     lf_putstr(file, "  int cpu_nr;\n");
1257     lf_putstr(file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
1258     lf_putstr(file, "    cpu_flush_icache(processors[cpu_nr]);\n");
1259     lf_putstr(file, "}\n");
1260   }
1261
1262   lf_putstr(file, "\n");
1263   lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
1264
1265   lf_putstr(file, "\n");
1266   lf_putstr(file, "if (setjmp(halt))\n");
1267   lf_putstr(file, "  return;\n");
1268
1269   lf_putstr(file, "\n");
1270   lf_putstr(file, "setjmp(restart);\n");
1271
1272   lf_putstr(file, "\n");
1273   if (!generate_smp) {
1274     lf_putstr(file, "processor = processors[0];\n");
1275     lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
1276   }
1277   else {
1278     lf_putstr(file, "current_cpu = psim_last_cpu(system);\n");
1279   }
1280
1281   if (!(code & generate_with_icache)) {
1282     lf_printf(file, "\n");
1283     lf_indent(file, -1);
1284     lf_printf(file, "idecode:\n");
1285     lf_indent(file, +1);
1286   }
1287
1288   print_jump(file, 0/*is_tail*/);
1289
1290   if ((code & generate_with_icache)) {
1291     lf_indent(file, -1);
1292     lf_printf(file, "cache_miss:\n");
1293     lf_indent(file, +1);
1294   }
1295
1296   lf_putstr(file, "instruction\n");
1297   lf_putstr(file, "  = vm_instruction_map_read(cpu_instruction_map(processor),\n");
1298   lf_putstr(file, "                            processor, nia);\n");
1299   print_idecode_body(file, table, "/*IGORE*/");
1300
1301   /* print out a table of all the internals functions */
1302   insn_table_traverse_function(table,
1303                                file, NULL,
1304                                print_jump_internal_function);
1305
1306  /* print out a table of all the instructions */
1307   if (generate_expanded_instructions)
1308     insn_table_traverse_tree(table,
1309                              file, cache_rules,
1310                              1,
1311                              NULL, /* start */
1312                              print_jump_definition, /* leaf */
1313                              NULL, /* end */
1314                              NULL); /* padding */
1315   else
1316     insn_table_traverse_insn(table,
1317                              file, cache_rules,
1318                              print_jump_definition);
1319   lf_indent(file, -2);
1320   lf_printf(file, "}\n");
1321 }
1322
1323
1324 /****************************************************************/
1325
1326
1327
1328 static void
1329 print_idecode_floating_point_unavailable(lf *file)
1330 {
1331   if ((code & generate_jumps))
1332     lf_printf(file, "goto %s_floating_point_unavailable;\n", (code & generate_with_icache) ? "icache" : "semantic");
1333   else if ((code & generate_with_icache))
1334     lf_printf(file, "return icache_floating_point_unavailable(%s);\n",
1335               ICACHE_FUNCTION_ACTUAL);
1336   else
1337     lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
1338               SEMANTIC_FUNCTION_ACTUAL);
1339 }
1340
1341
1342 /* Output code to do any final checks on the decoded instruction.
1343    This includes things like verifying any on decoded fields have the
1344    correct value and checking that (for floating point) floating point
1345    hardware isn't disabled */
1346
1347 void
1348 print_idecode_validate(lf *file,
1349                        insn *instruction,
1350                        opcode_field *opcodes)
1351 {
1352   /* Validate: unchecked instruction fields
1353
1354      If any constant fields in the instruction were not checked by the
1355      idecode tables, output code to check that they have the correct
1356      value here */
1357   { 
1358     unsigned check_mask = 0;
1359     unsigned check_val = 0;
1360     insn_field *field;
1361     opcode_field *opcode;
1362
1363     /* form check_mask/check_val containing what needs to be checked
1364        in the instruction */
1365     for (field = instruction->fields->first;
1366          field->first < insn_bit_size;
1367          field = field->next) {
1368
1369       check_mask <<= field->width;
1370       check_val <<= field->width;
1371
1372       /* is it a constant that could need validating? */
1373       if (!field->is_int && !field->is_slash)
1374         continue;
1375
1376       /* has it been checked by a table? */
1377       for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
1378         if (field->first >= opcode->first
1379             && field->last <= opcode->last)
1380           break;
1381       }
1382       if (opcode != NULL)
1383         continue;
1384
1385       check_mask |= (1 << field->width)-1;
1386       check_val |= field->val_int;
1387     }
1388
1389     /* if any bits not checked by opcode tables, output code to check them */
1390     if (check_mask) {
1391       lf_printf(file, "\n");
1392       lf_printf(file, "/* validate: %s */\n",
1393                 instruction->file_entry->fields[insn_format]);
1394       lf_printf(file, "if (WITH_RESERVED_BITS && (instruction & 0x%x) != 0x%x)\n",
1395                 check_mask, check_val);
1396       lf_indent(file, +2);
1397       print_idecode_illegal(file, "return");
1398       lf_indent(file, -2);
1399     }
1400   }
1401
1402   /* Validate floating point hardware
1403
1404      If the simulator is being built with out floating point hardware
1405      (different to it being disabled in the MSR) then floating point
1406      instructions are invalid */
1407   {
1408     if (it_is("f", instruction->file_entry->fields[insn_flags])) {
1409       lf_printf(file, "\n");
1410       lf_printf(file, "/* Validate: FP hardware exists */\n");
1411       lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
1412       lf_indent(file, +2);
1413       print_idecode_illegal(file, "return");
1414       lf_indent(file, -2);
1415     }
1416   }
1417
1418   /* Validate: Floating Point available
1419
1420      If floating point is not available, we enter a floating point
1421      unavailable interrupt into the cache instead of the instruction
1422      proper.
1423
1424      The PowerPC spec requires a CSI after MSR[FP] is changed and when
1425      ever a CSI occures we flush the instruction cache. */
1426
1427   {
1428     if (it_is("f", instruction->file_entry->fields[insn_flags])) {
1429       lf_printf(file, "\n");
1430       lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
1431       lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
1432       lf_indent(file, +2);
1433       print_idecode_floating_point_unavailable(file);
1434       lf_indent(file, -2);
1435     }
1436   }
1437 }
1438
1439
1440 /****************************************************************/
1441
1442
1443 static void
1444 print_idecode_run_function_header(lf *file,
1445                                   int can_stop,
1446                                   int is_definition)
1447 {
1448   int indent;
1449   lf_printf(file, "\n");
1450   lf_print_function_type(file, "void", "PSIM_INLINE_IDECODE", (is_definition ? " " : "\n"));
1451   indent = lf_putstr(file, (can_stop ? "idecode_run_until_stop" : "idecode_run"));
1452   if (is_definition)
1453     lf_putstr(file, "\n");
1454   else
1455     lf_indent(file, +indent);
1456   lf_putstr(file, "(psim *system,\n");
1457   if (can_stop)
1458     lf_putstr(file, " volatile int *keep_running,\n");
1459   lf_printf(file, " event_queue *events,\n");
1460   lf_putstr(file, " cpu *const processors[],\n");
1461   lf_putstr(file, " const int nr_cpus)");
1462   if (is_definition)
1463     lf_putstr(file, ";");
1464   else
1465     lf_indent(file, -indent);
1466   lf_putstr(file, "\n");
1467 }
1468
1469
1470 void
1471 gen_idecode_h(lf *file,
1472               insn_table *table,
1473               cache_table *cache_rules)
1474 {
1475   lf_printf(file, "/* The idecode_*.h functions shall move to support */\n");
1476   lf_printf(file, "#include \"idecode_expression.h\"\n");
1477   lf_printf(file, "#include \"idecode_fields.h\"\n");
1478   lf_printf(file, "#include \"idecode_branch.h\"\n");
1479   lf_printf(file, "\n");
1480   print_icache_struct(table, cache_rules, file);
1481   lf_printf(file, "\n");
1482   lf_printf(file, "#define WITH_IDECODE_SMP %d\n", generate_smp);
1483   lf_printf(file, "\n");
1484   print_idecode_run_function_header(file, 0/*can stop*/, 1/*is definition*/);
1485   print_idecode_run_function_header(file, 1/*can stop*/, 1/*is definition*/);
1486 }
1487
1488
1489 void
1490 gen_idecode_c(lf *file,
1491               insn_table *table,
1492               cache_table *cache_rules)
1493 {
1494   /* the intro */
1495   lf_printf(file, "#include \"inline.c\"\n");
1496   lf_printf(file, "\n");
1497   lf_printf(file, "#include \"cpu.h\"\n");
1498   lf_printf(file, "#include \"idecode.h\"\n");
1499   lf_printf(file, "#include \"semantics.h\"\n");
1500   lf_printf(file, "#include \"icache.h\"\n");
1501   lf_printf(file, "#ifdef HAVE_COMMON_FPU\n");
1502   lf_printf(file, "#include \"sim-inline.h\"\n");
1503   lf_printf(file, "#include \"sim-fpu.h\"\n");
1504   lf_printf(file, "#endif\n");
1505   lf_printf(file, "#include \"support.h\"\n");
1506   lf_printf(file, "\n");
1507   lf_printf(file, "#include <setjmp.h>\n");
1508   lf_printf(file, "\n");
1509   lf_printf(file, "enum {\n");
1510   lf_printf(file, "  /* greater or equal to zero => table */\n");
1511   lf_printf(file, "  function_entry = -1,\n");
1512   lf_printf(file, "  boolean_entry = -2,\n");
1513   lf_printf(file, "};\n");
1514   lf_printf(file, "\n");
1515   lf_printf(file, "typedef struct _idecode_table_entry {\n");
1516   lf_printf(file, "  int shift;\n");
1517   lf_printf(file, "  instruction_word mask;\n");
1518   lf_printf(file, "  instruction_word value;");
1519   lf_printf(file, "  void *function_or_table;\n");
1520   lf_printf(file, "} idecode_table_entry;\n");
1521   lf_printf(file, "\n");
1522   lf_printf(file, "\n");
1523
1524   if ((code & generate_calls)) {
1525
1526     print_idecode_lookups(file, table, cache_rules);
1527
1528     /* output the main idecode routine */
1529     print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
1530     print_run_until_stop_body(file, table, 0/* have stop argument */);
1531
1532     print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
1533     print_run_until_stop_body(file, table, 1/* no stop argument */);
1534
1535   }
1536   else if ((code & generate_jumps)) {
1537
1538     print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
1539     print_jump_until_stop_body(file, table, cache_rules, 0 /* have stop argument */);
1540
1541     print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
1542     print_jump_until_stop_body(file, table, cache_rules, 1/* have stop argument */);
1543
1544   }
1545   else {
1546     error("Something is wrong!\n");
1547   }
1548 }