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