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