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