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