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