]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/ppc/gen-icache.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / sim / ppc / gen-icache.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
22 #include "misc.h"
23 #include "lf.h"
24 #include "table.h"
25
26 #include "filter.h"
27
28 #include "ld-decode.h"
29 #include "ld-cache.h"
30 #include "ld-insn.h"
31
32 #include "igen.h"
33
34 #include "gen-semantics.h"
35 #include "gen-idecode.h"
36 #include "gen-icache.h"
37
38
39
40 static void
41 print_icache_function_header(lf *file,
42 const char *basename,
43 insn_bits *expanded_bits,
44 int is_function_definition)
45 {
46 lf_printf(file, "\n");
47 lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", " ");
48 print_function_name(file,
49 basename,
50 expanded_bits,
51 function_name_prefix_icache);
52 lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
53 if (!is_function_definition)
54 lf_printf(file, ";");
55 lf_printf(file, "\n");
56 }
57
58
59 void
60 print_icache_declaration(insn_table *entry,
61 lf *file,
62 void *data,
63 insn *instruction,
64 int depth)
65 {
66 if (generate_expanded_instructions) {
67 ASSERT(entry->nr_insn == 1);
68 print_icache_function_header(file,
69 entry->insns->file_entry->fields[insn_name],
70 entry->expanded_bits,
71 0/* is not function definition */);
72 }
73 else {
74 print_icache_function_header(file,
75 instruction->file_entry->fields[insn_name],
76 NULL,
77 0/* is not function definition */);
78 }
79 }
80
81
82
83 static void
84 print_icache_extraction(lf *file,
85 insn *instruction,
86 const char *entry_name,
87 const char *entry_type,
88 const char *entry_expression,
89 const char *original_name,
90 const char *file_name,
91 int line_nr,
92 insn_field *cur_field,
93 insn_bits *bits,
94 icache_decl_type what_to_declare,
95 icache_body_type what_to_do)
96 {
97 ASSERT(entry_name != NULL);
98
99 /* Define a storage area for the cache element */
100 if (what_to_declare == undef_variables) {
101 /* We've finished with the value - destory it */
102 lf_indent_suppress(file);
103 lf_printf(file, "#undef %s\n", entry_name);
104 return;
105 }
106 else if (what_to_declare == define_variables) {
107 lf_indent_suppress(file);
108 lf_printf(file, "#define %s ", entry_name);
109 }
110 else {
111 if (file_name != NULL)
112 lf_print__external_reference(file, line_nr, file_name);
113 lf_printf(file, "%s const %s UNUSED = ",
114 entry_type == NULL ? "unsigned" : entry_type,
115 entry_name);
116 }
117
118 /* define a value for that storage area as determined by what is in
119 the cache */
120 if (bits != NULL
121 && strcmp(entry_name, cur_field->val_string) == 0
122 && ((bits->opcode->is_boolean && bits->value == 0)
123 || (!bits->opcode->is_boolean))) {
124 /* The field has been made constant (as a result of expanding
125 instructions or similar). Remember that for a boolean field,
126 value is either 0 (implying the required boolean_constant) or
127 nonzero (implying some other value) - Define the variable
128 accordingly */
129 ASSERT(bits->field == cur_field);
130 ASSERT(entry_type == NULL);
131 if (bits->opcode->is_boolean)
132 lf_printf(file, "%d", bits->opcode->boolean_constant);
133 else if (bits->opcode->last < bits->field->last)
134 lf_printf(file, "%d",
135 bits->value << (bits->field->last - bits->opcode->last));
136 else
137 lf_printf(file, "%d", bits->value);
138 }
139 else if (bits != NULL
140 && bits->opcode->is_boolean
141 && original_name != NULL
142 && strncmp(entry_name,
143 original_name, strlen(original_name)) == 0
144 && strncmp(entry_name + strlen(original_name),
145 "_is_", strlen("_is_")) == 0
146 && (atol(entry_name + strlen(original_name) + strlen("_is_"))
147 == bits->opcode->boolean_constant)) {
148 /* An entry, derived from ORIGINAL_NAME, is testing to see of the
149 ORIGINAL_NAME has a specific constant value. That value
150 matching a boolean bit field */
151 lf_printf(file, "%d /* %s == %d */",
152 bits->value == 0, original_name, bits->opcode->boolean_constant);
153 }
154 else {
155 /* put the field in the local variable, possibly also enter it
156 into the cache */
157 /* handle the cache */
158 if ((what_to_do & get_values_from_icache)
159 || (what_to_do & put_values_in_icache)) {
160 lf_printf(file, "cache_entry->crack.%s.%s",
161 instruction->file_entry->fields[insn_form],
162 entry_name);
163 if (what_to_do & put_values_in_icache) /* also put it in the cache? */
164 lf_printf(file, " = ");
165 }
166 if ((what_to_do & put_values_in_icache)
167 || what_to_do == do_not_use_icache) {
168 if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0)
169 lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
170 i2target(hi_bit_nr, cur_field->first),
171 i2target(hi_bit_nr, cur_field->last));
172 else if (entry_expression != NULL)
173 lf_printf(file, "%s", entry_expression);
174 else
175 lf_printf(file, "eval_%s", entry_name);
176 }
177 }
178
179 if ((what_to_declare == define_variables)
180 || (what_to_declare == undef_variables))
181 lf_printf(file, "\n");
182 else
183 lf_printf(file, ";\n");
184 }
185
186
187 void
188 print_icache_body(lf *file,
189 insn *instruction,
190 insn_bits *expanded_bits,
191 cache_table *cache_rules,
192 icache_decl_type what_to_declare,
193 icache_body_type what_to_do)
194 {
195 insn_field *cur_field;
196
197 /* extract instruction fields */
198 lf_printf(file, "/* extraction: %s ",
199 instruction->file_entry->fields[insn_format]);
200 switch (what_to_declare) {
201 case define_variables:
202 lf_printf(file, "#define");
203 break;
204 case declare_variables:
205 lf_printf(file, "declare");
206 break;
207 case undef_variables:
208 lf_printf(file, "#undef");
209 break;
210 }
211 lf_printf(file, " ");
212 switch (what_to_do) {
213 case get_values_from_icache:
214 lf_printf(file, "get-values-from-icache");
215 break;
216 case put_values_in_icache:
217 lf_printf(file, "put-values-in-icache");
218 break;
219 case both_values_and_icache:
220 lf_printf(file, "get-values-from-icache|put-values-in-icache");
221 break;
222 case do_not_use_icache:
223 lf_printf(file, "do-not-use-icache");
224 break;
225 }
226 lf_printf(file, " */\n");
227
228 for (cur_field = instruction->fields->first;
229 cur_field->first < insn_bit_size;
230 cur_field = cur_field->next) {
231 if (cur_field->is_string) {
232 insn_bits *bits;
233 int found_rule = 0;
234 /* find any corresponding value */
235 for (bits = expanded_bits;
236 bits != NULL;
237 bits = bits->last) {
238 if (bits->field == cur_field)
239 break;
240 }
241 /* try the cache rule table for what to do */
242 {
243 cache_table *cache_rule;
244 for (cache_rule = cache_rules;
245 cache_rule != NULL;
246 cache_rule = cache_rule->next) {
247 if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
248 found_rule = 1;
249 if (cache_rule->type == scratch_value
250 && ((what_to_do & put_values_in_icache)
251 || what_to_do == do_not_use_icache))
252 print_icache_extraction(file,
253 instruction,
254 cache_rule->derived_name,
255 cache_rule->type_def,
256 cache_rule->expression,
257 cache_rule->field_name,
258 cache_rule->file_entry->file_name,
259 cache_rule->file_entry->line_nr,
260 cur_field,
261 bits,
262 what_to_declare,
263 do_not_use_icache);
264 else if (cache_rule->type == compute_value
265 && ((what_to_do & get_values_from_icache)
266 || what_to_do == do_not_use_icache))
267 print_icache_extraction(file,
268 instruction,
269 cache_rule->derived_name,
270 cache_rule->type_def,
271 cache_rule->expression,
272 cache_rule->field_name,
273 cache_rule->file_entry->file_name,
274 cache_rule->file_entry->line_nr,
275 cur_field,
276 bits,
277 what_to_declare,
278 do_not_use_icache);
279 else if (cache_rule->type == cache_value
280 && ((what_to_declare != undef_variables)
281 || !(what_to_do & put_values_in_icache)))
282 print_icache_extraction(file,
283 instruction,
284 cache_rule->derived_name,
285 cache_rule->type_def,
286 cache_rule->expression,
287 cache_rule->field_name,
288 cache_rule->file_entry->file_name,
289 cache_rule->file_entry->line_nr,
290 cur_field,
291 bits,
292 ((what_to_do & put_values_in_icache)
293 ? declare_variables
294 : what_to_declare),
295 what_to_do);
296 }
297 }
298 }
299 /* No rule at all, assume that it should go into the cache */
300 if (found_rule == 0
301 && ((what_to_declare != undef_variables)
302 || !(what_to_do & put_values_in_icache)))
303 print_icache_extraction(file,
304 instruction,
305 cur_field->val_string,
306 NULL, NULL, NULL, /* type, exp, orig */
307 instruction->file_entry->file_name,
308 instruction->file_entry->line_nr,
309 cur_field,
310 bits,
311 ((what_to_do & put_values_in_icache)
312 ? declare_variables
313 : what_to_declare),
314 what_to_do);
315 /* any thing else ... */
316 }
317 }
318
319 lf_print__internal_reference(file);
320
321 if ((code & generate_with_insn_in_icache)) {
322 lf_printf(file, "\n");
323 print_icache_extraction(file,
324 instruction,
325 "insn",
326 "instruction_word",
327 "instruction",
328 NULL, /* origin */
329 NULL, 0, /* file_name & line_nr */
330 NULL, NULL,
331 what_to_declare,
332 what_to_do);
333 }
334 }
335
336
337
338 typedef struct _icache_tree icache_tree;
339 struct _icache_tree {
340 char *name;
341 icache_tree *next;
342 icache_tree *children;
343 };
344
345 static icache_tree *
346 icache_tree_insert(icache_tree *tree,
347 char *name)
348 {
349 icache_tree *new_tree;
350 /* find it */
351 icache_tree **ptr_to_cur_tree = &tree->children;
352 icache_tree *cur_tree = *ptr_to_cur_tree;
353 while (cur_tree != NULL
354 && strcmp(cur_tree->name, name) < 0) {
355 ptr_to_cur_tree = &cur_tree->next;
356 cur_tree = *ptr_to_cur_tree;
357 }
358 ASSERT(cur_tree == NULL
359 || strcmp(cur_tree->name, name) >= 0);
360 /* already in the tree */
361 if (cur_tree != NULL
362 && strcmp(cur_tree->name, name) == 0)
363 return cur_tree;
364 /* missing, insert it */
365 ASSERT(cur_tree == NULL
366 || strcmp(cur_tree->name, name) > 0);
367 new_tree = ZALLOC(icache_tree);
368 new_tree->name = name;
369 new_tree->next = cur_tree;
370 *ptr_to_cur_tree = new_tree;
371 return new_tree;
372 }
373
374
375 static icache_tree *
376 insn_table_cache_fields(insn_table *table)
377 {
378 icache_tree *tree = ZALLOC(icache_tree);
379 insn *instruction;
380 for (instruction = table->insns;
381 instruction != NULL;
382 instruction = instruction->next) {
383 insn_field *field;
384 icache_tree *form =
385 icache_tree_insert(tree,
386 instruction->file_entry->fields[insn_form]);
387 for (field = instruction->fields->first;
388 field != NULL;
389 field = field->next) {
390 if (field->is_string)
391 icache_tree_insert(form, field->val_string);
392 }
393 }
394 return tree;
395 }
396
397
398
399 extern void
400 print_icache_struct(insn_table *instructions,
401 cache_table *cache_rules,
402 lf *file)
403 {
404 icache_tree *tree = insn_table_cache_fields(instructions);
405
406 lf_printf(file, "\n");
407 lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
408 (code & generate_with_icache) ? icache_size : 0);
409 lf_printf(file, "\n");
410
411 /* create an instruction cache if being used */
412 if ((code & generate_with_icache)) {
413 icache_tree *form;
414 lf_printf(file, "typedef struct _idecode_cache {\n");
415 lf_printf(file, " unsigned_word address;\n");
416 lf_printf(file, " void *semantic;\n");
417 lf_printf(file, " union {\n");
418 for (form = tree->children;
419 form != NULL;
420 form = form->next) {
421 icache_tree *field;
422 lf_printf(file, " struct {\n");
423 if (code & generate_with_insn_in_icache)
424 lf_printf(file, " instruction_word insn;\n");
425 for (field = form->children;
426 field != NULL;
427 field = field->next) {
428 cache_table *cache_rule;
429 int found_rule = 0;
430 for (cache_rule = cache_rules;
431 cache_rule != NULL;
432 cache_rule = cache_rule->next) {
433 if (strcmp(field->name, cache_rule->field_name) == 0) {
434 found_rule = 1;
435 if (cache_rule->derived_name != NULL)
436 lf_printf(file, " %s %s; /* %s */\n",
437 (cache_rule->type_def == NULL
438 ? "unsigned"
439 : cache_rule->type_def),
440 cache_rule->derived_name,
441 cache_rule->field_name);
442 }
443 }
444 if (!found_rule)
445 lf_printf(file, " unsigned %s;\n", field->name);
446 }
447 lf_printf(file, " } %s;\n", form->name);
448 }
449 lf_printf(file, " } crack;\n");
450 lf_printf(file, "} idecode_cache;\n");
451 }
452 else {
453 /* alernativly, since no cache, emit a dummy definition for
454 idecode_cache so that code refering to the type can still compile */
455 lf_printf(file, "typedef void idecode_cache;\n");
456 }
457 lf_printf(file, "\n");
458 }
459
460
461
462 static void
463 print_icache_function(lf *file,
464 insn *instruction,
465 insn_bits *expanded_bits,
466 opcode_field *opcodes,
467 cache_table *cache_rules)
468 {
469 int indent;
470
471 /* generate code to enter decoded instruction into the icache */
472 lf_printf(file, "\n");
473 lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", "\n");
474 indent = print_function_name(file,
475 instruction->file_entry->fields[insn_name],
476 expanded_bits,
477 function_name_prefix_icache);
478 lf_indent(file, +indent);
479 lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL);
480 lf_indent(file, -indent);
481
482 /* function header */
483 lf_printf(file, "{\n");
484 lf_indent(file, +2);
485
486 print_my_defines(file, expanded_bits, instruction->file_entry);
487 print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
488
489 print_idecode_validate(file, instruction, opcodes);
490
491 lf_printf(file, "\n");
492 lf_printf(file, "{\n");
493 lf_indent(file, +2);
494 if ((code & generate_with_semantic_icache))
495 lf_printf(file, "unsigned_word nia;\n");
496 print_icache_body(file,
497 instruction,
498 expanded_bits,
499 cache_rules,
500 ((code & generate_with_direct_access)
501 ? define_variables
502 : declare_variables),
503 ((code & generate_with_semantic_icache)
504 ? both_values_and_icache
505 : put_values_in_icache));
506
507 lf_printf(file, "\n");
508 lf_printf(file, "cache_entry->address = cia;\n");
509 lf_printf(file, "cache_entry->semantic = ");
510 print_function_name(file,
511 instruction->file_entry->fields[insn_name],
512 expanded_bits,
513 function_name_prefix_semantics);
514 lf_printf(file, ";\n");
515 lf_printf(file, "\n");
516
517 if ((code & generate_with_semantic_icache)) {
518 lf_printf(file, "/* semantic routine */\n");
519 print_semantic_body(file,
520 instruction,
521 expanded_bits,
522 opcodes);
523 lf_printf(file, "return nia;\n");
524 }
525
526 if (!(code & generate_with_semantic_icache)) {
527 lf_printf(file, "/* return the function proper */\n");
528 lf_printf(file, "return ");
529 print_function_name(file,
530 instruction->file_entry->fields[insn_name],
531 expanded_bits,
532 function_name_prefix_semantics);
533 lf_printf(file, ";\n");
534 }
535
536 if ((code & generate_with_direct_access))
537 print_icache_body(file,
538 instruction,
539 expanded_bits,
540 cache_rules,
541 undef_variables,
542 ((code & generate_with_semantic_icache)
543 ? both_values_and_icache
544 : put_values_in_icache));
545
546 lf_indent(file, -2);
547 lf_printf(file, "}\n");
548 lf_indent(file, -2);
549 lf_printf(file, "}\n");
550 }
551
552
553 void
554 print_icache_definition(insn_table *entry,
555 lf *file,
556 void *data,
557 insn *instruction,
558 int depth)
559 {
560 cache_table *cache_rules = (cache_table*)data;
561 if (generate_expanded_instructions) {
562 ASSERT(entry->nr_insn == 1
563 && entry->opcode == NULL
564 && entry->parent != NULL
565 && entry->parent->opcode != NULL);
566 ASSERT(entry->nr_insn == 1
567 && entry->opcode == NULL
568 && entry->parent != NULL
569 && entry->parent->opcode != NULL
570 && entry->parent->opcode_rule != NULL);
571 print_icache_function(file,
572 entry->insns,
573 entry->expanded_bits,
574 entry->opcode,
575 cache_rules);
576 }
577 else {
578 print_icache_function(file,
579 instruction,
580 NULL,
581 NULL,
582 cache_rules);
583 }
584 }
585
586
587
588 void
589 print_icache_internal_function_declaration(insn_table *table,
590 lf *file,
591 void *data,
592 table_entry *function)
593 {
594 ASSERT((code & generate_with_icache) != 0);
595 if (it_is("internal", function->fields[insn_flags])) {
596 lf_printf(file, "\n");
597 lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
598 "\n");
599 print_function_name(file,
600 function->fields[insn_name],
601 NULL,
602 function_name_prefix_icache);
603 lf_printf(file, "\n(%s);\n", ICACHE_FUNCTION_FORMAL);
604 }
605 }
606
607
608 void
609 print_icache_internal_function_definition(insn_table *table,
610 lf *file,
611 void *data,
612 table_entry *function)
613 {
614 ASSERT((code & generate_with_icache) != 0);
615 if (it_is("internal", function->fields[insn_flags])) {
616 lf_printf(file, "\n");
617 lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
618 "\n");
619 print_function_name(file,
620 function->fields[insn_name],
621 NULL,
622 function_name_prefix_icache);
623 lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL);
624 lf_printf(file, "{\n");
625 lf_indent(file, +2);
626 lf_printf(file, "/* semantic routine */\n");
627 table_entry_print_cpp_line_nr(file, function);
628 if ((code & generate_with_semantic_icache)) {
629 lf_print__c_code(file, function->annex);
630 lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
631 lf_printf(file, "return 0;\n");
632 }
633 else {
634 lf_printf(file, "return ");
635 print_function_name(file,
636 function->fields[insn_name],
637 NULL,
638 function_name_prefix_semantics);
639 lf_printf(file, ";\n");
640 }
641
642 lf_print__internal_reference(file);
643 lf_indent(file, -2);
644 lf_printf(file, "}\n");
645 }
646 }