New simulator changes from Andrew
[deliverable/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 lf_printf(file, "_%d_%d",
46 table->opcode->first,
47 table->opcode->last);
48 if (table->parent == NULL) break;
49 lf_printf(file, "__%d", table->opcode_nr);
50 table = table->parent;
51 }
52 }
53 }
54
55 /****************************************************************/
56
57
58 static void
59 lf_print_table_name(lf *file,
60 insn_table *table)
61 {
62 lf_printf(file, "idecode_table");
63 lf_print_opcodes(file, table);
64 }
65
66
67
68 static void
69 print_idecode_table(lf *file,
70 insn_table *entry,
71 const char *result)
72 {
73 /* int can_assume_leaf; */
74 decode_table *opcode_rule;
75
76 /* have a look at the rule table, if all table rules follow all
77 switch rules, I can assume that all end points are leaves */
78 opcode_rule = entry->opcode_rule;
79 while (opcode_rule != NULL
80 && (opcode_rule->gen == switch_gen
81 || opcode_rule->gen == padded_switch_gen))
82 opcode_rule = opcode_rule->next;
83
84 #if 0
85 /* FIXME: I don't get this bit! */
86 while (opcode_rule != NULL
87 && (opcode_rule->gen == switch_gen
88 || opcode_rule->gen == padded_switch_gen)
89 && opcode_rule->type != normal_decode_rule)
90 opcode_rule = opcode_rule->next;
91 can_assume_leaf = opcode_rule == NULL;
92 #endif
93
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 = EXTRACTED32(instruction, %d, %d);\n",
98 i2target(hi_bit_nr, entry->opcode->first),
99 i2target(hi_bit_nr, entry->opcode->last));
100 lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
101 lf_printf(file, "while (1) {\n");
102 lf_indent(file, +2);
103 {
104 lf_printf(file, "/* nonzero mask -> another table */\n");
105 lf_printf(file, "while (table_entry->shift >= 0) {\n");
106 lf_indent(file, +2);
107 {
108 lf_printf(file, "table = ((idecode_table_entry*)\n");
109 lf_printf(file, " table_entry->function_or_table);\n");
110 lf_printf(file, "opcode = ((instruction & table_entry->mask)\n");
111 lf_printf(file, " >> table_entry->shift);\n");
112 lf_printf(file, "table_entry = table + opcode;\n");
113 }
114 lf_indent(file, -2);
115 lf_printf(file, "}\n");
116 lf_printf(file, "ASSERT(table_entry->shift < 0);\n");
117 lf_printf(file, "/* found the leaf */\n");
118 lf_printf(file, "if (table_entry->shift == table_function_entry) {\n");
119 lf_indent(file, +2);
120 if ((code & generate_jumps)) {
121 lf_printf(file, "goto *table_entry->function_or_table;\n");
122 }
123 else {
124 lf_printf(file, "%s ", result);
125 if ((code & generate_with_icache)) {
126 lf_printf(file, "(((idecode_icache*)table_entry->function_or_table)\n");
127 lf_printf(file, " (%s));\n", ICACHE_FUNCTION_ACTUAL);
128 }
129 else {
130 lf_printf(file, "((idecode_semantic*)table_entry->function_or_table)\n");
131 lf_printf(file, " (%s);\n", SEMANTIC_FUNCTION_ACTUAL);
132 }
133 }
134 lf_printf(file, "break;\n");
135 lf_indent(file, -2);
136 lf_printf(file, "}\n");
137 lf_printf(file, "/* must be a boolean */\n");
138 lf_printf(file, "opcode = (((instruction << table_entry->left)\n");
139 lf_printf(file, " >> table_entry->right)\n");
140 lf_printf(file, " != table_entry->mask);\n");
141 lf_printf(file, "table = ((idecode_table_entry*)\n");
142 lf_printf(file, " table_entry->function_or_table);\n");
143 lf_printf(file, "table_entry = table + opcode;\n");
144 }
145 lf_indent(file, -2);
146 lf_printf(file, "}\n");
147 }
148
149
150 static void
151 print_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
166 static void
167 print_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 if (entry->opcode == NULL) {
179 /* table leaf entry */
180 lf_printf(file, " /*%d*/ { table_function_entry, 0, 0, 0, ", entry->opcode_nr);
181 if ((code & generate_jumps))
182 lf_printf(file, "&&");
183 print_function_name(file,
184 entry->insns->file_entry->fields[insn_name],
185 entry->expanded_bits,
186 ((code & generate_with_icache)
187 ? function_name_prefix_icache
188 : function_name_prefix_semantics));
189 lf_printf(file, " },\n");
190 }
191 else if (entry->opcode_rule->gen == 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 void print_idecode_switch
254 (lf *file,
255 insn_table *table,
256 const char *result);
257
258
259 static void
260 idecode_switch_start(insn_table *table,
261 lf *file,
262 void *data,
263 int depth)
264 {
265 /* const char *result = data; */
266 ASSERT(depth == 0);
267 ASSERT(table->opcode_rule->gen == switch_gen
268 || table->opcode_rule->gen == padded_switch_gen
269 || table->opcode_rule->gen == goto_gen);
270
271 switch (table->opcode_rule->gen) {
272 default:
273 lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
274 i2target(hi_bit_nr, table->opcode->first),
275 i2target(hi_bit_nr, table->opcode->last));
276 break;
277 }
278 }
279
280
281 static void
282 idecode_switch_leaf(insn_table *entry,
283 lf *file,
284 void *data,
285 insn *instruction,
286 int depth)
287 {
288 const char *result = data;
289 ASSERT(entry->parent != NULL);
290 ASSERT(depth == 0);
291 ASSERT(entry->parent->opcode_rule->gen == switch_gen
292 || entry->parent->opcode_rule->gen == padded_switch_gen);
293 ASSERT(entry->parent->opcode);
294
295 if (entry->parent->opcode->is_boolean
296 && entry->opcode_nr == 0)
297 lf_printf(file, "case %d:\n", entry->parent->opcode->boolean_constant);
298 else if (!entry->parent->opcode->is_boolean)
299 lf_printf(file, "case %d:\n", entry->opcode_nr);
300 else
301 lf_printf(file, "default:\n");
302 lf_indent(file, +2);
303 {
304 if (entry->opcode == NULL) {
305 /* switch calling leaf */
306 if ((code & generate_jumps))
307 lf_printf(file, "goto ");
308 if ((code & generate_calls))
309 lf_printf(file, "%s ", result);
310 print_function_name(file,
311 entry->insns->file_entry->fields[insn_name],
312 entry->expanded_bits,
313 ((code & generate_with_icache)
314 ? function_name_prefix_icache
315 : function_name_prefix_semantics));
316 if ((code & generate_calls))
317 lf_printf(file, "(%s)", SEMANTIC_FUNCTION_ACTUAL);
318 lf_printf(file, ";\n");
319 }
320 else if (entry->opcode_rule->gen == switch_gen
321 || entry->opcode_rule->gen == padded_switch_gen) {
322 /* switch calling switch */
323 print_idecode_switch(file, entry, result);
324 }
325 else {
326 /* switch looking up a table */
327 lf_printf(file, "{\n");
328 lf_indent(file, -2);
329 print_idecode_table(file, entry, result);
330 lf_indent(file, -2);
331 lf_printf(file, "}\n");
332 }
333 lf_printf(file, "break;\n");
334 }
335 lf_indent(file, -2);
336 }
337
338
339 static void
340 print_idecode_switch_illegal(lf *file,
341 const char *result)
342 {
343 lf_indent(file, +2);
344 print_idecode_illegal(file, result);
345 /*lf_printf(file, "break;\n");*/
346 lf_indent(file, -2);
347 }
348
349 static void
350 idecode_switch_end(insn_table *table,
351 lf *file,
352 void *data,
353 int depth)
354 {
355 const char *result = data;
356 ASSERT(depth == 0);
357 ASSERT(table->opcode_rule->gen == switch_gen
358 || table->opcode_rule->gen == padded_switch_gen
359 || table->opcode_rule->gen == goto_gen);
360 ASSERT(table->opcode);
361
362 if (!table->opcode->is_boolean) {
363 lf_printf(file, "default:\n");
364 switch (table->opcode_rule->gen) {
365 case switch_gen:
366 print_idecode_switch_illegal(file, result);
367 break;
368 case padded_switch_gen:
369 lf_printf(file, " error(\"Internal error - bad switch generated\\n\");\n");
370 lf_printf(file, " break;\n");
371 break;
372 default:
373 error("idecode_switch_end - unknown switch type\n");
374 }
375 }
376 lf_printf(file, "}\n");
377 }
378
379 static void
380 idecode_switch_padding(insn_table *table,
381 lf *file,
382 void *data,
383 int depth,
384 int opcode_nr)
385 {
386 const char *result = data;
387 ASSERT(depth == 0);
388 ASSERT(table->opcode_rule->gen == switch_gen
389 || table->opcode_rule->gen == padded_switch_gen);
390
391 if (table->opcode_rule->gen == padded_switch_gen) {
392 lf_printf(file, "case %d:\n", opcode_nr);
393 print_idecode_switch_illegal(file, result);
394 }
395 else if (table->opcode_rule->gen == goto_gen) {
396 lf_printf(file, "goto_%d:\n", opcode_nr);
397 print_idecode_switch_illegal(file, result);
398 }
399 }
400
401
402 void
403 print_idecode_switch(lf *file,
404 insn_table *table,
405 const char *result)
406 {
407 insn_table_traverse_tree(table,
408 file, (void*)result,
409 0,
410 idecode_switch_start,
411 idecode_switch_leaf,
412 idecode_switch_end,
413 idecode_switch_padding);
414 }
415
416
417 static void
418 print_idecode_switch_function_header(lf *file,
419 insn_table *table,
420 int is_function_definition)
421 {
422 lf_printf(file, "\n");
423 if ((code & generate_calls)) {
424 lf_printf(file, "static ");
425 if ((code & generate_with_icache))
426 lf_printf(file, "idecode_semantic *");
427 else
428 lf_printf(file, "unsigned_word");
429 if (is_function_definition)
430 lf_printf(file, "\n");
431 else
432 lf_printf(file, " ");
433 lf_print_table_name(file, table);
434 lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
435 if (!is_function_definition)
436 lf_printf(file, ";");
437 lf_printf(file, "\n");
438 }
439 if ((code & generate_jumps) && is_function_definition) {
440 lf_indent(file, -1);
441 lf_print_table_name(file, table);
442 lf_printf(file, ":\n");
443 lf_indent(file, +1);
444 }
445 }
446
447
448 static void
449 idecode_declare_if_switch(insn_table *table,
450 lf *file,
451 void *data,
452 int depth)
453 {
454 if ((table->opcode_rule->gen == switch_gen
455 || table->opcode_rule->gen == padded_switch_gen)
456 && table->parent != NULL /* don't declare the top one yet */
457 && table->parent->opcode_rule->gen == array_gen) {
458 print_idecode_switch_function_header(file,
459 table,
460 0/*isnt function definition*/);
461 }
462 }
463
464
465 static void
466 idecode_expand_if_switch(insn_table *table,
467 lf *file,
468 void *data,
469 int depth)
470 {
471 if ((table->opcode_rule->gen == switch_gen
472 || table->opcode_rule->gen == padded_switch_gen)
473 && table->parent != NULL /* don't expand the top one yet */
474 && table->parent->opcode_rule->gen == array_gen) {
475 print_idecode_switch_function_header(file,
476 table,
477 1/*is function definition*/);
478 if ((code & generate_calls)) {
479 lf_printf(file, "{\n");
480 lf_indent(file, +2);
481 }
482 print_idecode_switch(file, table, "return");
483 if ((code & generate_calls)) {
484 lf_indent(file, -2);
485 lf_printf(file, "}\n");
486 }
487 }
488 }
489
490
491 /****************************************************************/
492
493
494 static void
495 print_idecode_lookups(lf *file,
496 insn_table *table,
497 cache_table *cache_rules)
498 {
499 int depth;
500
501 /* output switch function declarations where needed by tables */
502 insn_table_traverse_tree(table,
503 file, NULL,
504 1,
505 idecode_declare_if_switch, /* START */
506 NULL, NULL, NULL);
507
508 /* output tables where needed */
509 for (depth = insn_table_depth(table);
510 depth > 0;
511 depth--) {
512 insn_table_traverse_tree(table,
513 file, NULL,
514 1-depth,
515 print_idecode_table_start,
516 print_idecode_table_leaf,
517 print_idecode_table_end,
518 print_idecode_table_padding);
519 }
520
521 /* output switch functions where needed */
522 insn_table_traverse_tree(table,
523 file, NULL,
524 1,
525 idecode_expand_if_switch, /* START */
526 NULL, NULL, NULL);
527 }
528
529
530 static void
531 print_idecode_body(lf *file,
532 insn_table *table,
533 const char *result,
534 const char *indent)
535 {
536 lf_indent(file, +strlen(indent));
537 lf_putstr(file, "{\n");
538 lf_indent(file, +2);
539 if (table->opcode_rule->gen == switch_gen
540 || table->opcode_rule->gen == padded_switch_gen)
541 print_idecode_switch(file, table, result);
542 else
543 print_idecode_table(file, table, result);
544 lf_indent(file, -2);
545 lf_putstr(file, "}\n");
546 lf_indent(file, -strlen(indent));
547 }
548
549
550 /****************************************************************/
551
552
553 static void
554 print_run_until_stop_body(lf *file,
555 insn_table *table,
556 int can_stop)
557 {
558 /* Output the function to execute real code:
559
560 Unfortunatly, there are multiple cases to consider vis:
561
562 <icache> X <smp> X <events> X <keep-running-flag> X ...
563
564 Consequently this function is written in multiple different ways */
565
566 lf_putstr(file, "{\n");
567 lf_indent(file, +2);
568 if (!can_stop)
569 lf_putstr(file, "int *keep_running = NULL;\n");
570 lf_putstr(file, "jmp_buf halt;\n");
571 lf_putstr(file, "jmp_buf restart;\n");
572 lf_putstr(file, "cpu *processor = NULL;\n");
573 lf_putstr(file, "unsigned_word cia = -1;\n");
574 lf_putstr(file, "instruction_word instruction = 0;\n");
575 if (generate_smp) {
576 lf_putstr(file, "int current_cpu = -1;\n");
577 }
578 if ((code & generate_with_icache)) {
579 lf_putstr(file, "idecode_cache *cache_entry = NULL;\n");
580 }
581
582 if ((code & generate_with_icache)) {
583 lf_putstr(file, "\n");
584 lf_putstr(file, "{\n");
585 lf_putstr(file, " int cpu_nr;\n");
586 lf_putstr(file, " for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
587 lf_putstr(file, " cpu_flush_icache(processors[cpu_nr]);\n");
588 lf_putstr(file, "}\n");
589 }
590
591 lf_putstr(file, "\n");
592 lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
593
594 lf_putstr(file, "\n");
595 lf_putstr(file, "if (setjmp(halt))\n");
596 lf_putstr(file, " return;\n");
597
598 lf_putstr(file, "\n");
599 lf_putstr(file, "setjmp(restart);\n");
600
601 if (!generate_smp) {
602
603 lf_putstr(file, "
604 /* CASE 1: NO SMP (with or with out instruction cache).
605
606 In this case, we can take advantage of the fact that the current
607 instruction address does not need to be returned to the cpu object
608 after every execution of an instruction. Instead it only needs to
609 be saved when either A. the main loop exits or B. A cpu-halt or
610 cpu-restart call forces the loop to be re-enered. The later
611 functions always save the current cpu instruction address.
612
613 Two subcases also exist that with and that without an instruction
614 cache. */");
615
616 lf_putstr(file, "\n\n");
617
618 lf_putstr(file, "processor = processors[0];\n");
619 lf_putstr(file, "cia = cpu_get_program_counter(processor);\n");
620 lf_putstr(file, "while (1) {\n");
621 lf_indent(file, +2);
622 lf_putstr(file, "if (WITH_EVENTS) {\n");
623 lf_putstr(file, " if (event_queue_tick(events)) {\n");
624 lf_putstr(file, " cpu_set_program_counter(processor, cia);\n");
625 lf_putstr(file, " event_queue_process(events);\n");
626 lf_putstr(file, " cia = cpu_get_program_counter(processor);\n");
627 lf_putstr(file, " }\n");
628 lf_putstr(file, "}\n");
629
630 if (!(code & generate_with_icache)) {
631 lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
632 print_idecode_body(file, table, "cia =", "");
633 }
634
635 if ((code & generate_with_icache)) {
636 lf_putstr(file, "cache_entry = cpu_icache_entry(processor, cia);\n");
637 lf_putstr(file, "if (cache_entry->address == cia) {\n");
638 lf_putstr(file, " /* cache hit */\n");
639 lf_putstr(file, " idecode_semantic *const semantic = cache_entry->semantic;\n");
640 lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n");
641 lf_putstr(file, "}\n");
642 lf_putstr(file, "else {\n");
643 lf_putstr(file, " /* cache miss */\n");
644 if (!(code & generate_with_semantic_icache)) {
645 lf_indent(file, +2);
646 lf_putstr(file, "idecode_semantic *semantic;\n");
647 lf_indent(file, -2);
648 }
649 lf_putstr(file, " instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
650 lf_putstr(file, " if (WITH_MON != 0)\n");
651 lf_putstr(file, " mon_event(mon_event_icache_miss, processor, cia);\n");
652 if ((code & generate_with_semantic_icache)) {
653 print_idecode_body(file, table, "cia =", " ");
654 }
655 else {
656 print_idecode_body(file, table, "semantic =", " ");
657 lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n");
658 }
659 lf_putstr(file, "}\n");
660 }
661
662 lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
663 lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
664 lf_indent(file, -2);
665 lf_putstr(file, "}\n");
666 }
667
668 if (generate_smp) {
669
670 lf_putstr(file, "
671 /* CASE 2: SMP (With or without ICACHE)
672
673 The complexity here comes from needing to correctly restart the
674 system when it is aborted. In particular if cpu0 requests a
675 restart, the next cpu is still cpu1. Cpu0 being restarted after
676 all the other CPU's and the event queue have been processed */");
677
678 lf_putstr(file, "\n\n");
679
680 lf_putstr(file, "current_cpu = psim_last_cpu(system);\n");
681 lf_putstr(file, "while (1) {\n");
682 lf_indent(file, +2);
683 lf_putstr(file, "if (WITH_EVENTS) {\n");
684 lf_putstr(file, " current_cpu += 1;\n");
685 lf_putstr(file, " if (current_cpu == nr_cpus) {\n");
686 lf_putstr(file, " if (event_queue_tick(events)) {\n");
687 lf_putstr(file, " event_queue_process(events);\n");
688 lf_putstr(file, " }\n");
689 lf_putstr(file, " current_cpu = 0;\n");
690 lf_putstr(file, " }\n");
691 lf_putstr(file, "}\n");
692 lf_putstr(file, "else {\n");
693 lf_putstr(file, " current_cpu = (current_cpu + 1) % nr_cpus;\n");
694 lf_putstr(file, "}\n");
695 lf_putstr(file, "processor = processors[current_cpu];\n");
696 lf_putstr(file, "cia = cpu_get_program_counter(processor);\n");
697
698 if (!(code & generate_with_icache)) {
699 lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
700 print_idecode_body(file, table, "cia =", "");
701 }
702
703 if ((code & generate_with_icache)) {
704 lf_putstr(file, "cache_entry = cpu_icache_entry(processor, cia);\n");
705 lf_putstr(file, "if (cache_entry->address == cia) {\n");
706 lf_putstr(file, " /* cache hit */\n");
707 lf_putstr(file, " idecode_semantic *semantic = cache_entry->semantic;\n");
708 lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n");
709 lf_putstr(file, "}\n");
710 lf_putstr(file, "else {\n");
711 lf_putstr(file, " /* cache miss */\n");
712 if (!(code & generate_with_semantic_icache)) {
713 lf_indent(file, +2);
714 lf_putstr(file, " idecode_semantic *semantic;\n");
715 lf_indent(file, -2);
716 }
717 lf_putstr(file, " instruction =\n");
718 lf_putstr(file, " vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
719 lf_putstr(file, " if (WITH_MON != 0)\n");
720 lf_putstr(file, " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
721 if ((code & generate_with_semantic_icache)) {
722 print_idecode_body(file, table, "cia =", " ");
723 }
724 else {
725 print_idecode_body(file, table, "semantic = ", " ");
726 lf_indent(file, +2);
727 lf_putstr(file, "cia = semantic(processor, cache_entry, cia));\n");
728 lf_indent(file, -2);
729 }
730 lf_putstr(file, "}\n");
731 }
732
733 lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
734 lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
735 lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
736 lf_indent(file, -2);
737 lf_putstr(file, "}\n");
738 }
739
740
741 lf_indent(file, -2);
742 lf_putstr(file, "}\n");
743 }
744
745
746 /****************************************************************/
747
748 static void
749 print_jump(lf *file,
750 int is_tail)
751 {
752 if (is_tail) {
753 lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
754 lf_putstr(file, " cpu_halt(processor, nia, was_continuing, 0/*na*/);\n");
755 }
756
757 if (!generate_smp) {
758 lf_putstr(file, "if (WITH_EVENTS) {\n");
759 lf_putstr(file, " if (event_queue_tick(events)) {\n");
760 lf_putstr(file, " cpu_set_program_counter(processor, nia);\n");
761 lf_putstr(file, " event_queue_process(events);\n");
762 lf_putstr(file, " nia = cpu_get_program_counter(processor);\n");
763 lf_putstr(file, " }\n");
764 lf_putstr(file, "}\n");
765 }
766
767 if (generate_smp) {
768 lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
769 lf_putstr(file, "if (WITH_EVENTS) {\n");
770 lf_putstr(file, " current_cpu += 1;\n");
771 lf_putstr(file, " if (current_cpu == nr_cpus) {\n");
772 lf_putstr(file, " if (event_queue_tick(events)) {\n");
773 lf_putstr(file, " event_queue_process(events);\n");
774 lf_putstr(file, " }\n");
775 lf_putstr(file, " current_cpu = 0;\n");
776 lf_putstr(file, " }\n");
777 lf_putstr(file, "}\n");
778 lf_putstr(file, "else {\n");
779 lf_putstr(file, " current_cpu = (current_cpu + 1) % nr_cpus;\n");
780 lf_putstr(file, "}\n");
781 lf_putstr(file, "processor = processors[current_cpu];\n");
782 lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
783 }
784
785 if ((code & generate_with_icache)) {
786 lf_putstr(file, "cache_entry = cpu_icache_entry(processor, nia);\n");
787 lf_putstr(file, "if (cache_entry->address == nia) {\n");
788 lf_putstr(file, " /* cache hit */\n");
789 lf_putstr(file, " goto *cache_entry->semantic;\n");
790 lf_putstr(file, "}\n");
791 if (is_tail) {
792 lf_putstr(file, "goto cache_miss;\n");
793 }
794 }
795
796 if (!(code & generate_with_icache)) {
797 lf_printf(file, "goto idecode;\n");
798 }
799
800 }
801
802
803
804
805
806 static void
807 print_jump_insn(lf *file,
808 insn *instruction,
809 insn_bits *expanded_bits,
810 opcode_field *opcodes,
811 cache_table *cache_rules)
812 {
813
814 /* what we are for the moment */
815 lf_printf(file, "\n");
816 print_define_my_index(file, instruction->file_entry);
817
818 /* output the icache entry */
819 if ((code & generate_with_icache)) {
820 lf_printf(file, "\n");
821 lf_indent(file, -1);
822 print_function_name(file,
823 instruction->file_entry->fields[insn_name],
824 expanded_bits,
825 function_name_prefix_icache);
826 lf_printf(file, ":\n");
827 lf_indent(file, +1);
828 lf_printf(file, "{\n");
829 lf_indent(file, +2);
830 lf_putstr(file, "const unsigned_word cia = nia;\n");
831 print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
832 print_idecode_validate(file, instruction, opcodes);
833 lf_printf(file, "\n");
834 lf_printf(file, "{\n");
835 lf_indent(file, +2);
836 print_icache_body(file,
837 instruction,
838 expanded_bits,
839 cache_rules,
840 0,
841 0/*get_value_from_cache*/,
842 1/*put_value_in_cache*/);
843 lf_printf(file, "cache_entry->address = nia;\n");
844 lf_printf(file, "cache_entry->semantic = &&");
845 print_function_name(file,
846 instruction->file_entry->fields[insn_name],
847 expanded_bits,
848 function_name_prefix_semantics);
849 lf_printf(file, ";\n");
850 if ((code & generate_with_semantic_icache)) {
851 print_semantic_body(file,
852 instruction,
853 expanded_bits,
854 opcodes);
855 print_jump(file, 1/*is-tail*/);
856 }
857 else {
858 lf_printf(file, "/* goto ");
859 print_function_name(file,
860 instruction->file_entry->fields[insn_name],
861 expanded_bits,
862 function_name_prefix_semantics);
863 lf_printf(file, "; */\n");
864 }
865 lf_indent(file, -2);
866 lf_putstr(file, "}\n");
867 lf_indent(file, -2);
868 lf_printf(file, "}\n");
869 }
870
871 /* print the semantics */
872 lf_printf(file, "\n");
873 lf_indent(file, -1);
874 print_function_name(file,
875 instruction->file_entry->fields[insn_name],
876 expanded_bits,
877 function_name_prefix_semantics);
878 lf_printf(file, ":\n");
879 lf_indent(file, +1);
880 lf_printf(file, "{\n");
881 lf_indent(file, +2);
882 lf_putstr(file, "const unsigned_word cia = nia;\n");
883 print_icache_body(file,
884 instruction,
885 expanded_bits,
886 cache_rules,
887 (code & generate_with_direct_access_icache),
888 (code & generate_with_icache)/*get_value_from_cache*/,
889 0/*put_value_in_cache*/);
890 print_semantic_body(file,
891 instruction,
892 expanded_bits,
893 opcodes);
894 print_jump(file, 1/*is tail*/);
895 lf_indent(file, -2);
896 lf_printf(file, "}\n");
897 }
898
899 static void
900 print_jump_definition(insn_table *entry,
901 lf *file,
902 void *data,
903 insn *instruction,
904 int depth)
905 {
906 cache_table *cache_rules = (cache_table*)data;
907 if (generate_expanded_instructions) {
908 ASSERT(entry->nr_insn == 1
909 && entry->opcode == NULL
910 && entry->parent != NULL
911 && entry->parent->opcode != NULL);
912 ASSERT(entry->nr_insn == 1
913 && entry->opcode == NULL
914 && entry->parent != NULL
915 && entry->parent->opcode != NULL
916 && entry->parent->opcode_rule != NULL);
917 print_jump_insn(file,
918 entry->insns,
919 entry->expanded_bits,
920 entry->opcode,
921 cache_rules);
922 }
923 else {
924 print_jump_insn(file,
925 instruction,
926 NULL,
927 NULL,
928 cache_rules);
929 }
930 }
931
932
933 static void
934 print_jump_internal_function(insn_table *table,
935 lf *file,
936 void *data,
937 table_entry *function)
938 {
939 if (it_is("internal", function->fields[insn_flags])) {
940 lf_printf(file, "\n");
941 table_entry_print_cpp_line_nr(file, function);
942 lf_indent(file, -1);
943 print_function_name(file,
944 function->fields[insn_name],
945 NULL,
946 ((code & generate_with_icache)
947 ? function_name_prefix_icache
948 : function_name_prefix_semantics));
949 lf_printf(file, ":\n");
950 lf_indent(file, +1);
951 lf_printf(file, "{\n");
952 lf_indent(file, +2);
953 lf_printf(file, "const unsigned_word cia = nia;\n");
954 lf_print__c_code(file, function->annex);
955 lf_print__internal_reference(file);
956 lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
957 lf_indent(file, -2);
958 lf_printf(file, "}\n");
959 }
960 }
961
962 static void
963 print_jump_until_stop_body(lf *file,
964 insn_table *table,
965 cache_table *cache_rules,
966 int can_stop)
967 {
968 lf_printf(file, "{\n");
969 lf_indent(file, +2);
970 if (!can_stop)
971 lf_printf(file, "int *keep_running = NULL;\n");
972 lf_putstr(file, "jmp_buf halt;\n");
973 lf_putstr(file, "jmp_buf restart;\n");
974 lf_putstr(file, "cpu *processor = NULL;\n");
975 lf_putstr(file, "unsigned_word nia = -1;\n");
976 lf_putstr(file, "instruction_word instruction = 0;\n");
977 if ((code & generate_with_icache)) {
978 lf_putstr(file, "idecode_cache *cache_entry = NULL;\n");
979 }
980 if (generate_smp) {
981 lf_putstr(file, "int current_cpu = -1;\n");
982 }
983
984 /* all the switches and tables - they know about jumping */
985 print_idecode_lookups(file, table, cache_rules);
986
987 /* start the simulation up */
988 if ((code & generate_with_icache)) {
989 lf_putstr(file, "\n");
990 lf_putstr(file, "{\n");
991 lf_putstr(file, " int cpu_nr;\n");
992 lf_putstr(file, " for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
993 lf_putstr(file, " cpu_flush_icache(processors[cpu_nr]);\n");
994 lf_putstr(file, "}\n");
995 }
996
997 lf_putstr(file, "\n");
998 lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
999
1000 lf_putstr(file, "\n");
1001 lf_putstr(file, "if (setjmp(halt))\n");
1002 lf_putstr(file, " return;\n");
1003
1004 lf_putstr(file, "\n");
1005 lf_putstr(file, "setjmp(restart);\n");
1006
1007 lf_putstr(file, "\n");
1008 if (!generate_smp) {
1009 lf_putstr(file, "processor = processors[0];\n");
1010 lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
1011 }
1012 else {
1013 lf_putstr(file, "current_cpu = psim_last_cpu(system);\n");
1014 }
1015
1016 if (!(code & generate_with_icache)) {
1017 lf_printf(file, "\n");
1018 lf_indent(file, -1);
1019 lf_printf(file, "idecode:\n");
1020 lf_indent(file, +1);
1021 }
1022
1023 print_jump(file, 0/*is_tail*/);
1024
1025 if ((code & generate_with_icache)) {
1026 lf_indent(file, -1);
1027 lf_printf(file, "cache_miss:\n");
1028 lf_indent(file, +1);
1029 }
1030
1031 lf_putstr(file, "instruction\n");
1032 lf_putstr(file, " = vm_instruction_map_read(cpu_instruction_map(processor),\n");
1033 lf_putstr(file, " processor, nia);\n");
1034 print_idecode_body(file, table, "/*IGORE*/", "");
1035
1036 /* print out a table of all the internals functions */
1037 insn_table_traverse_function(table,
1038 file, NULL,
1039 print_jump_internal_function);
1040
1041 /* print out a table of all the instructions */
1042 if (generate_expanded_instructions)
1043 insn_table_traverse_tree(table,
1044 file, cache_rules,
1045 1,
1046 NULL, /* start */
1047 print_jump_definition, /* leaf */
1048 NULL, /* end */
1049 NULL); /* padding */
1050 else
1051 insn_table_traverse_insn(table,
1052 file, cache_rules,
1053 print_jump_definition);
1054 lf_indent(file, -2);
1055 lf_printf(file, "}\n");
1056 }
1057
1058
1059 /****************************************************************/
1060
1061
1062
1063 static void
1064 print_idecode_floating_point_unavailable(lf *file)
1065 {
1066 if ((code & generate_jumps))
1067 lf_printf(file, "goto %s_floating_point_unavailable;\n", (code & generate_with_icache) ? "icache" : "semantic");
1068 else if ((code & generate_with_icache))
1069 lf_printf(file, "return icache_floating_point_unavailable(%s);\n",
1070 ICACHE_FUNCTION_ACTUAL);
1071 else
1072 lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
1073 SEMANTIC_FUNCTION_ACTUAL);
1074 }
1075
1076
1077 /* Output code to do any final checks on the decoded instruction.
1078 This includes things like verifying any on decoded fields have the
1079 correct value and checking that (for floating point) floating point
1080 hardware isn't disabled */
1081
1082 void
1083 print_idecode_validate(lf *file,
1084 insn *instruction,
1085 opcode_field *opcodes)
1086 {
1087 /* Validate: unchecked instruction fields
1088
1089 If any constant fields in the instruction were not checked by the
1090 idecode tables, output code to check that they have the correct
1091 value here */
1092 {
1093 unsigned check_mask = 0;
1094 unsigned check_val = 0;
1095 insn_field *field;
1096 opcode_field *opcode;
1097
1098 /* form check_mask/check_val containing what needs to be checked
1099 in the instruction */
1100 for (field = instruction->fields->first;
1101 field->first < insn_bit_size;
1102 field = field->next) {
1103
1104 check_mask <<= field->width;
1105 check_val <<= field->width;
1106
1107 /* is it a constant that could need validating? */
1108 if (!field->is_int && !field->is_slash)
1109 continue;
1110
1111 /* has it been checked by a table? */
1112 for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
1113 if (field->first >= opcode->first
1114 && field->last <= opcode->last)
1115 break;
1116 }
1117 if (opcode != NULL)
1118 continue;
1119
1120 check_mask |= (1 << field->width)-1;
1121 check_val |= field->val_int;
1122 }
1123
1124 /* if any bits not checked by opcode tables, output code to check them */
1125 if (check_mask) {
1126 lf_printf(file, "\n");
1127 lf_printf(file, "/* validate: %s */\n",
1128 instruction->file_entry->fields[insn_format]);
1129 lf_printf(file, "if (WITH_RESERVED_BITS && (instruction & 0x%x) != 0x%x)\n",
1130 check_mask, check_val);
1131 lf_indent(file, +2);
1132 print_idecode_illegal(file, "return");
1133 lf_indent(file, -2);
1134 }
1135 }
1136
1137 /* Validate floating point hardware
1138
1139 If the simulator is being built with out floating point hardware
1140 (different to it being disabled in the MSR) then floating point
1141 instructions are invalid */
1142 {
1143 if (it_is("f", instruction->file_entry->fields[insn_flags])) {
1144 lf_printf(file, "\n");
1145 lf_printf(file, "/* Validate: FP hardware exists */\n");
1146 lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
1147 lf_indent(file, +2);
1148 print_idecode_illegal(file, "return");
1149 lf_indent(file, -2);
1150 }
1151 }
1152
1153 /* Validate: Floating Point available
1154
1155 If floating point is not available, we enter a floating point
1156 unavailable interrupt into the cache instead of the instruction
1157 proper.
1158
1159 The PowerPC spec requires a CSI after MSR[FP] is changed and when
1160 ever a CSI occures we flush the instruction cache. */
1161
1162 {
1163 if (it_is("f", instruction->file_entry->fields[insn_flags])) {
1164 lf_printf(file, "\n");
1165 lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
1166 lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
1167 lf_indent(file, +2);
1168 print_idecode_floating_point_unavailable(file);
1169 lf_indent(file, -2);
1170 }
1171 }
1172 }
1173
1174
1175 /****************************************************************/
1176
1177
1178 static void
1179 print_idecode_run_function_header(lf *file,
1180 int can_stop,
1181 int is_definition)
1182 {
1183 int indent;
1184 lf_printf(file, "\n");
1185 lf_print_function_type(file, "void", "INLINE_IDECODE", (is_definition ? " " : "\n"));
1186 indent = lf_putstr(file, (can_stop ? "idecode_run_until_stop" : "idecode_run"));
1187 if (is_definition)
1188 lf_putstr(file, "\n");
1189 else
1190 lf_indent(file, +indent);
1191 lf_putstr(file, "(psim *system,\n");
1192 if (can_stop)
1193 lf_putstr(file, " volatile int *keep_running,\n");
1194 lf_printf(file, " event_queue *events,\n");
1195 lf_putstr(file, " cpu *const processors[],\n");
1196 lf_putstr(file, " const int nr_cpus)");
1197 if (is_definition)
1198 lf_putstr(file, ";");
1199 else
1200 lf_indent(file, -indent);
1201 lf_putstr(file, "\n");
1202 }
1203
1204
1205 void
1206 gen_idecode_h(lf *file,
1207 insn_table *table,
1208 cache_table *cache_rules)
1209 {
1210 lf_printf(file, "/* The idecode_*.h functions shall move to support */\n");
1211 lf_printf(file, "#include \"idecode_expression.h\"\n");
1212 lf_printf(file, "#include \"idecode_fields.h\"\n");
1213 lf_printf(file, "#include \"idecode_branch.h\"\n");
1214 lf_printf(file, "\n");
1215 print_icache_struct(table, cache_rules, file);
1216 lf_printf(file, "\n");
1217 lf_printf(file, "#define WITH_IDECODE_SMP %d\n", generate_smp);
1218 lf_printf(file, "\n");
1219 print_idecode_run_function_header(file, 0/*can stop*/, 1/*is definition*/);
1220 print_idecode_run_function_header(file, 1/*can stop*/, 1/*is definition*/);
1221 }
1222
1223
1224 void
1225 gen_idecode_c(lf *file,
1226 insn_table *table,
1227 cache_table *cache_rules)
1228 {
1229 /* the intro */
1230 lf_printf(file, "#include \"inline.c\"\n");
1231 lf_printf(file, "\n");
1232 lf_printf(file, "#include \"cpu.h\"\n");
1233 lf_printf(file, "#include \"idecode.h\"\n");
1234 lf_printf(file, "#include \"semantics.h\"\n");
1235 lf_printf(file, "#include \"icache.h\"\n");
1236 lf_printf(file, "#include \"support.h\"\n");
1237 lf_printf(file, "\n");
1238 lf_printf(file, "#include <setjmp.h>\n");
1239 lf_printf(file, "\n");
1240 lf_printf(file, "/* encodings for a negative shift field */\n");
1241 lf_printf(file, "enum {\n");
1242 lf_printf(file, " table_boolean_entry = -2,\n");
1243 lf_printf(file, " table_function_entry = -1,\n");
1244 lf_printf(file, "};\n");
1245 lf_printf(file, "\n");
1246 lf_printf(file, "typedef struct _idecode_table_entry {\n");
1247 lf_printf(file, " signed short shift; /* shift >= 0: t[(i & mask) >> shift] */\n");
1248 lf_printf(file, " unsigned char left; /* shift == -2: */\n");
1249 lf_printf(file, " unsigned char right; /* t[((i << left) >> right) != mask] */\n");
1250 lf_printf(file, " unsigned mask; /* else (shift == -1): function() */\n");
1251 lf_printf(file, " void *function_or_table;\n");
1252 lf_printf(file, "} idecode_table_entry;\n");
1253 lf_printf(file, "\n");
1254 lf_printf(file, "\n");
1255
1256 if ((code & generate_calls)) {
1257
1258 print_idecode_lookups(file, table, cache_rules);
1259
1260 /* output the main idecode routine */
1261 print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
1262 print_run_until_stop_body(file, table, 0/* have stop argument */);
1263
1264 print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
1265 print_run_until_stop_body(file, table, 1/* no stop argument */);
1266
1267 }
1268 else if ((code & generate_jumps)) {
1269
1270 print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
1271 print_jump_until_stop_body(file, table, cache_rules, 0 /* have stop argument */);
1272
1273 print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
1274 print_jump_until_stop_body(file, table, cache_rules, 1/* have stop argument */);
1275
1276 }
1277 else {
1278 error("Something is wrong!\n");
1279 }
1280 }
1281
1282
This page took 0.056215 seconds and 4 git commands to generate.