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