]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/ppc/gen-idecode.c
Initial creation of sourceware repository
[thirdparty/binutils-gdb.git] / sim / ppc / gen-idecode.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21 #include "misc.h"
22 #include "lf.h"
23 #include "table.h"
24
25 #include "filter.h"
26
27 #include "ld-decode.h"
28 #include "ld-cache.h"
29 #include "ld-insn.h"
30
31 #include "igen.h"
32
33 #include "gen-idecode.h"
34 #include "gen-icache.h"
35 #include "gen-semantics.h"
36
37
38
39 static void
40 lf_print_opcodes(lf *file,
41 insn_table *table)
42 {
43 if (table != NULL) {
44 while (1) {
45 ASSERT(table->opcode != NULL);
46 lf_printf(file, "_%d_%d",
47 table->opcode->first,
48 table->opcode->last);
49 if (table->parent == NULL) break;
50 lf_printf(file, "__%d", table->opcode_nr);
51 table = table->parent;
52 }
53 }
54 }
55
56 /****************************************************************/
57
58
59 static void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, "
761 /* CASE 1: NO SMP (with or with out instruction cache).
762
763 In this case, we can take advantage of the fact that the current
764 instruction address does not need to be returned to the cpu object
765 after every execution of an instruction. Instead it only needs to
766 be saved when either A. the main loop exits or B. A cpu-halt or
767 cpu-restart call forces the loop to be re-enered. The later
768 functions always save the current cpu instruction address.
769
770 Two subcases also exist that with and that without an instruction
771 cache.
772
773 An additional complexity is the need to ensure that a 1:1 ratio
774 is maintained between the execution of an instruction and the
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, "
871 /* CASE 2: SMP (With or without ICACHE)
872
873 The complexity here comes from needing to correctly restart the
874 system when it is aborted. In particular if cpu0 requests a
875 restart, the next cpu is still cpu1. Cpu0 being restarted after
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
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
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
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
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
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
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
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
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", "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
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
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, "#include \"support.h\"\n");
1503 lf_printf(file, "\n");
1504 lf_printf(file, "#include <setjmp.h>\n");
1505 lf_printf(file, "\n");
1506 lf_printf(file, "enum {\n");
1507 lf_printf(file, " /* greater or equal to zero => table */\n");
1508 lf_printf(file, " function_entry = -1,\n");
1509 lf_printf(file, " boolean_entry = -2,\n");
1510 lf_printf(file, "};\n");
1511 lf_printf(file, "\n");
1512 lf_printf(file, "typedef struct _idecode_table_entry {\n");
1513 lf_printf(file, " int shift;\n");
1514 lf_printf(file, " instruction_word mask;\n");
1515 lf_printf(file, " instruction_word value;");
1516 lf_printf(file, " void *function_or_table;\n");
1517 lf_printf(file, "} idecode_table_entry;\n");
1518 lf_printf(file, "\n");
1519 lf_printf(file, "\n");
1520
1521 if ((code & generate_calls)) {
1522
1523 print_idecode_lookups(file, table, cache_rules);
1524
1525 /* output the main idecode routine */
1526 print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
1527 print_run_until_stop_body(file, table, 0/* have stop argument */);
1528
1529 print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
1530 print_run_until_stop_body(file, table, 1/* no stop argument */);
1531
1532 }
1533 else if ((code & generate_jumps)) {
1534
1535 print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
1536 print_jump_until_stop_body(file, table, cache_rules, 0 /* have stop argument */);
1537
1538 print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
1539 print_jump_until_stop_body(file, table, cache_rules, 1/* have stop argument */);
1540
1541 }
1542 else {
1543 error("Something is wrong!\n");
1544 }
1545 }