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