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