Automatic date update in version.in
[binutils-gdb.git] / sim / ppc / gen-icache.c
blobde483bae1de9d86ee5499360e205a1405d9dd70b
1 /* This file is part of the program psim.
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
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 3 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <stdlib.h>
22 #include "misc.h"
23 #include "lf.h"
24 #include "lf-ppc.h"
25 #include "table.h"
27 #include "filter.h"
28 #include "filter-ppc.h"
30 #include "ld-decode.h"
31 #include "ld-cache.h"
32 #include "ld-insn.h"
34 #include "igen.h"
36 #include "gen-semantics.h"
37 #include "gen-idecode.h"
38 #include "gen-icache.h"
42 static void
43 print_icache_function_header(lf *file,
44 const char *basename,
45 insn_bits *expanded_bits,
46 int is_function_definition)
48 lf_printf(file, "\n");
49 lf_print__function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", " ");
50 print_function_name(file,
51 basename,
52 expanded_bits,
53 function_name_prefix_icache);
54 lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
55 if (!is_function_definition)
56 lf_printf(file, ";");
57 lf_printf(file, "\n");
61 void
62 print_icache_declaration(insn_table *entry,
63 lf *file,
64 void *data,
65 insn *instruction,
66 int depth)
68 if (generate_expanded_instructions) {
69 ASSERT(entry->nr_insn == 1);
70 print_icache_function_header(file,
71 entry->insns->file_entry->fields[insn_name],
72 entry->expanded_bits,
73 0/* is not function definition */);
75 else {
76 print_icache_function_header(file,
77 instruction->file_entry->fields[insn_name],
78 NULL,
79 0/* is not function definition */);
85 static void
86 print_icache_extraction(lf *file,
87 insn *instruction,
88 const char *entry_name,
89 const char *entry_type,
90 const char *entry_expression,
91 const char *original_name,
92 const char *file_name,
93 int line_nr,
94 insn_field *cur_field,
95 insn_bits *bits,
96 icache_decl_type what_to_declare,
97 icache_body_type what_to_do,
98 const char *reason)
100 const char *expression;
101 ASSERT(entry_name != NULL);
103 /* Define a storage area for the cache element */
104 if (what_to_declare == undef_variables) {
105 /* We've finished with the value - destroy it */
106 lf_indent_suppress(file);
107 lf_printf(file, "#undef %s\n", entry_name);
108 return;
110 else if (what_to_declare == define_variables) {
111 lf_indent_suppress(file);
112 lf_printf(file, "#define %s ", entry_name);
114 else {
115 if (file_name != NULL)
116 lf_print__external_ref(file, line_nr, file_name);
117 lf_printf(file, "%s const %s ATTRIBUTE_UNUSED = ",
118 entry_type == NULL ? "unsigned" : entry_type,
119 entry_name);
122 /* define a value for that storage area as determined by what is in
123 the cache */
124 if (bits != NULL
125 && strcmp(entry_name, cur_field->val_string) == 0
126 && ((bits->opcode->is_boolean && bits->value == 0)
127 || (!bits->opcode->is_boolean))) {
128 /* The simple field has been made constant (as a result of
129 expanding instructions or similar). Remember that for a
130 boolean field, value is either 0 (implying the required
131 boolean_constant) or nonzero (implying some other value and
132 handled later below) - Define the variable accordingly */
133 expression = "constant field";
134 ASSERT(bits->field == cur_field);
135 ASSERT(entry_type == NULL);
136 if (bits->opcode->is_boolean)
137 lf_printf(file, "%d", bits->opcode->boolean_constant);
138 else if (bits->opcode->last < bits->field->last)
139 lf_printf(file, "%d",
140 bits->value << (bits->field->last - bits->opcode->last));
141 else
142 lf_printf(file, "%d", bits->value);
144 else if (bits != NULL
145 && original_name != NULL
146 && strncmp(entry_name,
147 original_name, strlen(original_name)) == 0
148 && strncmp(entry_name + strlen(original_name),
149 "_is_", strlen("_is_")) == 0
150 && ((bits->opcode->is_boolean
151 && (atol(entry_name + strlen(original_name) + strlen("_is_"))
152 == bits->opcode->boolean_constant))
153 || (!bits->opcode->is_boolean))) {
154 expression = "constant compare";
155 /* An entry, derived from ORIGINAL_NAME, is testing to see of the
156 ORIGINAL_NAME has a specific constant value. That value
157 matching a boolean or constant field */
158 if (bits->opcode->is_boolean)
159 lf_printf(file, "%d /* %s == %d */",
160 bits->value == 0,
161 original_name,
162 bits->opcode->boolean_constant);
163 else if (bits->opcode->last < bits->field->last)
164 lf_printf(file, "%d /* %s == %d */",
165 (atol(entry_name + strlen(original_name) + strlen("_is_"))
166 == (bits->value << (bits->field->last - bits->opcode->last))),
167 original_name,
168 (bits->value << (bits->field->last - bits->opcode->last)));
169 else
170 lf_printf(file, "%d /* %s == %d */",
171 (atol(entry_name + strlen(original_name) + strlen("_is_"))
172 == bits->value),
173 original_name,
174 bits->value);
176 else {
177 /* put the field in the local variable, possibly also enter it
178 into the cache */
179 expression = "extraction";
180 /* handle the cache */
181 if ((what_to_do & get_values_from_icache)
182 || (what_to_do & put_values_in_icache)) {
183 lf_printf(file, "cache_entry->crack.%s.%s",
184 instruction->file_entry->fields[insn_form],
185 entry_name);
186 if (what_to_do & put_values_in_icache) /* also put it in the cache? */
187 lf_printf(file, " = ");
189 if ((what_to_do & put_values_in_icache)
190 || what_to_do == do_not_use_icache) {
191 if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0)
192 lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
193 i2target(hi_bit_nr, cur_field->first),
194 i2target(hi_bit_nr, cur_field->last));
195 else if (entry_expression != NULL)
196 lf_printf(file, "%s", entry_expression);
197 else
198 lf_printf(file, "eval_%s", entry_name);
202 if (!((what_to_declare == define_variables)
203 || (what_to_declare == undef_variables)))
204 lf_printf(file, ";");
205 if (reason != NULL)
206 lf_printf(file, " /* %s - %s */", reason, expression);
207 lf_printf(file, "\n");
211 void
212 print_icache_body(lf *file,
213 insn *instruction,
214 insn_bits *expanded_bits,
215 cache_table *cache_rules,
216 icache_decl_type what_to_declare,
217 icache_body_type what_to_do)
219 insn_field *cur_field;
221 /* extract instruction fields */
222 lf_printf(file, "/* extraction: %s ",
223 instruction->file_entry->fields[insn_format]);
224 switch (what_to_declare) {
225 case define_variables:
226 lf_printf(file, "#define");
227 break;
228 case declare_variables:
229 lf_printf(file, "declare");
230 break;
231 case undef_variables:
232 lf_printf(file, "#undef");
233 break;
235 lf_printf(file, " ");
236 switch (what_to_do) {
237 case get_values_from_icache:
238 lf_printf(file, "get-values-from-icache");
239 break;
240 case put_values_in_icache:
241 lf_printf(file, "put-values-in-icache");
242 break;
243 case both_values_and_icache:
244 lf_printf(file, "get-values-from-icache|put-values-in-icache");
245 break;
246 case do_not_use_icache:
247 lf_printf(file, "do-not-use-icache");
248 break;
250 lf_printf(file, " */\n");
252 for (cur_field = instruction->fields->first;
253 cur_field->first < insn_bit_size;
254 cur_field = cur_field->next) {
255 if (cur_field->is_string) {
256 insn_bits *bits;
257 int found_rule = 0;
258 /* find any corresponding value */
259 for (bits = expanded_bits;
260 bits != NULL;
261 bits = bits->last) {
262 if (bits->field == cur_field)
263 break;
265 /* try the cache rule table for what to do */
267 cache_table *cache_rule;
268 for (cache_rule = cache_rules;
269 cache_rule != NULL;
270 cache_rule = cache_rule->next) {
271 if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
272 found_rule = 1;
273 if (cache_rule->type == scratch_value
274 && ((what_to_do & put_values_in_icache)
275 || what_to_do == do_not_use_icache))
276 print_icache_extraction(file,
277 instruction,
278 cache_rule->derived_name,
279 cache_rule->type_def,
280 cache_rule->expression,
281 cache_rule->field_name,
282 cache_rule->file_entry->file_name,
283 cache_rule->file_entry->line_nr,
284 cur_field,
285 bits,
286 what_to_declare,
287 do_not_use_icache,
288 "icache scratch");
289 else if (cache_rule->type == compute_value
290 && ((what_to_do & get_values_from_icache)
291 || what_to_do == do_not_use_icache))
292 print_icache_extraction(file,
293 instruction,
294 cache_rule->derived_name,
295 cache_rule->type_def,
296 cache_rule->expression,
297 cache_rule->field_name,
298 cache_rule->file_entry->file_name,
299 cache_rule->file_entry->line_nr,
300 cur_field,
301 bits,
302 what_to_declare,
303 do_not_use_icache,
304 "semantic compute");
305 else if (cache_rule->type == cache_value
306 && ((what_to_declare != undef_variables)
307 || !(what_to_do & put_values_in_icache)))
308 print_icache_extraction(file,
309 instruction,
310 cache_rule->derived_name,
311 cache_rule->type_def,
312 cache_rule->expression,
313 cache_rule->field_name,
314 cache_rule->file_entry->file_name,
315 cache_rule->file_entry->line_nr,
316 cur_field,
317 bits,
318 ((what_to_do & put_values_in_icache)
319 ? declare_variables
320 : what_to_declare),
321 what_to_do,
322 "in icache");
326 /* No rule at all, assume that this is needed in the semantic
327 function (when values are extracted from the icache) and
328 hence must be put into the cache */
329 if (found_rule == 0
330 && ((what_to_declare != undef_variables)
331 || !(what_to_do & put_values_in_icache)))
332 print_icache_extraction(file,
333 instruction,
334 cur_field->val_string,
335 NULL, NULL, NULL, /* type, exp, orig */
336 instruction->file_entry->file_name,
337 instruction->file_entry->line_nr,
338 cur_field,
339 bits,
340 ((what_to_do & put_values_in_icache)
341 ? declare_variables
342 : what_to_declare),
343 what_to_do,
344 "default in icache");
345 /* any thing else ... */
349 lf_print__internal_ref(file);
351 if ((code & generate_with_insn_in_icache)) {
352 lf_printf(file, "\n");
353 print_icache_extraction(file,
354 instruction,
355 "insn",
356 "instruction_word",
357 "instruction",
358 NULL, /* origin */
359 NULL, 0, /* file_name & line_nr */
360 NULL, NULL,
361 what_to_declare,
362 what_to_do,
363 NULL);
369 typedef struct _icache_tree icache_tree;
370 struct _icache_tree {
371 const char *name;
372 icache_tree *next;
373 icache_tree *children;
376 static icache_tree *
377 icache_tree_insert(icache_tree *tree,
378 const char *name)
380 icache_tree *new_tree;
381 /* find it */
382 icache_tree **ptr_to_cur_tree = &tree->children;
383 icache_tree *cur_tree = *ptr_to_cur_tree;
384 while (cur_tree != NULL
385 && strcmp(cur_tree->name, name) < 0) {
386 ptr_to_cur_tree = &cur_tree->next;
387 cur_tree = *ptr_to_cur_tree;
389 ASSERT(cur_tree == NULL
390 || strcmp(cur_tree->name, name) >= 0);
391 /* already in the tree */
392 if (cur_tree != NULL
393 && strcmp(cur_tree->name, name) == 0)
394 return cur_tree;
395 /* missing, insert it */
396 ASSERT(cur_tree == NULL
397 || strcmp(cur_tree->name, name) > 0);
398 new_tree = ZALLOC(icache_tree);
399 new_tree->name = name;
400 new_tree->next = cur_tree;
401 *ptr_to_cur_tree = new_tree;
402 return new_tree;
406 static icache_tree *
407 insn_table_cache_fields(insn_table *table)
409 icache_tree *tree = ZALLOC(icache_tree);
410 insn *instruction;
411 for (instruction = table->insns;
412 instruction != NULL;
413 instruction = instruction->next) {
414 insn_field *field;
415 icache_tree *form =
416 icache_tree_insert(tree,
417 instruction->file_entry->fields[insn_form]);
418 for (field = instruction->fields->first;
419 field != NULL;
420 field = field->next) {
421 if (field->is_string)
422 icache_tree_insert(form, field->val_string);
425 return tree;
430 extern void
431 print_icache_struct(insn_table *instructions,
432 cache_table *cache_rules,
433 lf *file)
435 icache_tree *tree = insn_table_cache_fields(instructions);
437 lf_printf(file, "\n");
438 lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
439 (code & generate_with_icache) ? icache_size : 0);
440 lf_printf(file, "\n");
442 /* create an instruction cache if being used */
443 if ((code & generate_with_icache)) {
444 icache_tree *form;
445 lf_printf(file, "typedef struct _idecode_cache {\n");
446 lf_printf(file, " unsigned_word address;\n");
447 lf_printf(file, " void *semantic;\n");
448 lf_printf(file, " union {\n");
449 for (form = tree->children;
450 form != NULL;
451 form = form->next) {
452 icache_tree *field;
453 lf_printf(file, " struct {\n");
454 if (code & generate_with_insn_in_icache)
455 lf_printf(file, " instruction_word insn;\n");
456 for (field = form->children;
457 field != NULL;
458 field = field->next) {
459 cache_table *cache_rule;
460 int found_rule = 0;
461 for (cache_rule = cache_rules;
462 cache_rule != NULL;
463 cache_rule = cache_rule->next) {
464 if (strcmp(field->name, cache_rule->field_name) == 0) {
465 found_rule = 1;
466 if (cache_rule->derived_name != NULL)
467 lf_printf(file, " %s %s; /* %s */\n",
468 (cache_rule->type_def == NULL
469 ? "unsigned"
470 : cache_rule->type_def),
471 cache_rule->derived_name,
472 cache_rule->field_name);
475 if (!found_rule)
476 lf_printf(file, " unsigned %s;\n", field->name);
478 lf_printf(file, " } %s;\n", form->name);
480 lf_printf(file, " } crack;\n");
481 lf_printf(file, "} idecode_cache;\n");
483 else {
484 /* alernativly, since no cache, emit a dummy definition for
485 idecode_cache so that code referring to the type can still compile */
486 lf_printf(file, "typedef void idecode_cache;\n");
488 lf_printf(file, "\n");
493 static void
494 print_icache_function(lf *file,
495 insn *instruction,
496 insn_bits *expanded_bits,
497 opcode_field *opcodes,
498 cache_table *cache_rules)
500 int indent;
502 /* generate code to enter decoded instruction into the icache */
503 lf_printf(file, "\n");
504 lf_print__function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", "\n");
505 indent = print_function_name(file,
506 instruction->file_entry->fields[insn_name],
507 expanded_bits,
508 function_name_prefix_icache);
509 lf_indent(file, +indent);
510 lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL);
511 lf_indent(file, -indent);
513 /* function header */
514 lf_printf(file, "{\n");
515 lf_indent(file, +2);
517 print_my_defines(file, expanded_bits, instruction->file_entry);
518 print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
520 print_idecode_validate(file, instruction, opcodes);
522 lf_printf(file, "\n");
523 lf_printf(file, "{\n");
524 lf_indent(file, +2);
525 if ((code & generate_with_semantic_icache))
526 lf_printf(file, "unsigned_word nia;\n");
527 print_icache_body(file,
528 instruction,
529 expanded_bits,
530 cache_rules,
531 ((code & generate_with_direct_access)
532 ? define_variables
533 : declare_variables),
534 ((code & generate_with_semantic_icache)
535 ? both_values_and_icache
536 : put_values_in_icache));
538 lf_printf(file, "\n");
539 lf_printf(file, "cache_entry->address = cia;\n");
540 lf_printf(file, "cache_entry->semantic = ");
541 print_function_name(file,
542 instruction->file_entry->fields[insn_name],
543 expanded_bits,
544 function_name_prefix_semantics);
545 lf_printf(file, ";\n");
546 lf_printf(file, "\n");
548 if ((code & generate_with_semantic_icache)) {
549 lf_printf(file, "/* semantic routine */\n");
550 print_semantic_body(file,
551 instruction,
552 expanded_bits,
553 opcodes);
554 lf_printf(file, "return nia;\n");
557 if (!(code & generate_with_semantic_icache)) {
558 lf_printf(file, "/* return the function proper */\n");
559 lf_printf(file, "return ");
560 print_function_name(file,
561 instruction->file_entry->fields[insn_name],
562 expanded_bits,
563 function_name_prefix_semantics);
564 lf_printf(file, ";\n");
567 if ((code & generate_with_direct_access))
568 print_icache_body(file,
569 instruction,
570 expanded_bits,
571 cache_rules,
572 undef_variables,
573 ((code & generate_with_semantic_icache)
574 ? both_values_and_icache
575 : put_values_in_icache));
577 lf_indent(file, -2);
578 lf_printf(file, "}\n");
579 lf_indent(file, -2);
580 lf_printf(file, "}\n");
584 void
585 print_icache_definition(insn_table *entry,
586 lf *file,
587 void *data,
588 insn *instruction,
589 int depth)
591 cache_table *cache_rules = (cache_table*)data;
592 if (generate_expanded_instructions) {
593 ASSERT(entry->nr_insn == 1
594 && entry->opcode == NULL
595 && entry->parent != NULL
596 && entry->parent->opcode != NULL);
597 ASSERT(entry->nr_insn == 1
598 && entry->opcode == NULL
599 && entry->parent != NULL
600 && entry->parent->opcode != NULL
601 && entry->parent->opcode_rule != NULL);
602 print_icache_function(file,
603 entry->insns,
604 entry->expanded_bits,
605 entry->opcode,
606 cache_rules);
608 else {
609 print_icache_function(file,
610 instruction,
611 NULL,
612 NULL,
613 cache_rules);
619 void
620 print_icache_internal_function_declaration(insn_table *table,
621 lf *file,
622 void *data,
623 table_entry *function)
625 ASSERT((code & generate_with_icache) != 0);
626 if (it_is("internal", function->fields[insn_flags])) {
627 lf_printf(file, "\n");
628 lf_print__function_type(file, ICACHE_FUNCTION_TYPE, "PSIM_INLINE_ICACHE",
629 "\n");
630 print_function_name(file,
631 function->fields[insn_name],
632 NULL,
633 function_name_prefix_icache);
634 lf_printf(file, "\n(%s);\n", ICACHE_FUNCTION_FORMAL);
639 void
640 print_icache_internal_function_definition(insn_table *table,
641 lf *file,
642 void *data,
643 table_entry *function)
645 ASSERT((code & generate_with_icache) != 0);
646 if (it_is("internal", function->fields[insn_flags])) {
647 lf_printf(file, "\n");
648 lf_print__function_type(file, ICACHE_FUNCTION_TYPE, "PSIM_INLINE_ICACHE",
649 "\n");
650 print_function_name(file,
651 function->fields[insn_name],
652 NULL,
653 function_name_prefix_icache);
654 lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL);
655 lf_printf(file, "{\n");
656 lf_indent(file, +2);
657 lf_printf(file, "/* semantic routine */\n");
658 table_entry_print_cpp_line_nr(file, function);
659 if ((code & generate_with_semantic_icache)) {
660 lf_print__c_code(file, function->annex);
661 lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
662 lf_printf(file, "return 0;\n");
664 else {
665 lf_printf(file, "return ");
666 print_function_name(file,
667 function->fields[insn_name],
668 NULL,
669 function_name_prefix_semantics);
670 lf_printf(file, ";\n");
673 lf_print__internal_ref(file);
674 lf_indent(file, -2);
675 lf_printf(file, "}\n");