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