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