gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / sim / ppc / gen-idecode.c
CommitLineData
c906108c
SS
1/* This file is part of the program psim.
2
8d64d0fd 3 Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
c906108c
SS
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
3fd725ef 7 the Free Software Foundation; either version 3 of the License, or
c906108c
SS
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
51b318de 16 along with this program; if not, see <http://www.gnu.org/licenses/>.
c906108c
SS
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
38static void
39lf_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
58static void
59lf_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
68static void
69print_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
124static void
125print_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
140static void
141print_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
199static void
200print_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
211static void
212print_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
232static void
233print_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
248static void
249print_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
265static void
266print_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
280static void
281print_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
290static void
291print_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
310void print_idecode_switch
311(lf *file,
312 insn_table *table,
313 const char *result);
314
315static void
316idecode_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
361static void
362idecode_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
448static void
449print_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
458static void
459idecode_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
511static void
512idecode_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
540void
541print_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
555static void
556print_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
586static void
587idecode_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
604static void
605idecode_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
634static void
635print_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
670static void
671print_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
687static void
688print_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
d7a97a9b
DD
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\
c906108c
SS
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
d7a97a9b
DD
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\
c906108c
SS
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
1001static void
1002print_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
1060static void
1061print_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
1164static void
1165print_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
1198static void
1199print_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
1227static void
1228print_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
1328static void
1329print_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
1347void
1348print_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
1443static void
1444print_idecode_run_function_header(lf *file,
1445 int can_stop,
1446 int is_definition)
1447{
1448 int indent;
1449 lf_printf(file, "\n");
d29d5195 1450 lf_print_function_type(file, "void", "PSIM_INLINE_IDECODE", (is_definition ? " " : "\n"));
c906108c
SS
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
1470void
1471gen_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
1489void
1490gen_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");
8d64d0fd
AC
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");
c906108c
SS
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}
This page took 1.000326 seconds and 4 git commands to generate.