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/>.
28 #include "filter-ppc.h"
30 #include "ld-decode.h"
36 #include "gen-semantics.h"
37 #include "gen-idecode.h"
38 #include "gen-icache.h"
43 print_icache_function_header(lf
*file
,
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
,
53 function_name_prefix_icache
);
54 lf_printf(file
, "\n(%s)", ICACHE_FUNCTION_FORMAL
);
55 if (!is_function_definition
)
57 lf_printf(file
, "\n");
62 print_icache_declaration(insn_table
*entry
,
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
],
73 0/* is not function definition */);
76 print_icache_function_header(file
,
77 instruction
->file_entry
->fields
[insn_name
],
79 0/* is not function definition */);
86 print_icache_extraction(lf
*file
,
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
,
94 insn_field
*cur_field
,
96 icache_decl_type what_to_declare
,
97 icache_body_type what_to_do
,
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
);
110 else if (what_to_declare
== define_variables
) {
111 lf_indent_suppress(file
);
112 lf_printf(file
, "#define %s ", entry_name
);
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
,
122 /* define a value for that storage area as determined by what is in
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
));
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 */",
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
))),
168 (bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
)));
170 lf_printf(file
, "%d /* %s == %d */",
171 (atol(entry_name
+ strlen(original_name
) + strlen("_is_"))
177 /* put the field in the local variable, possibly also enter it
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
],
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
);
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
, ";");
206 lf_printf(file
, " /* %s - %s */", reason
, expression
);
207 lf_printf(file
, "\n");
212 print_icache_body(lf
*file
,
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");
228 case declare_variables
:
229 lf_printf(file
, "declare");
231 case undef_variables
:
232 lf_printf(file
, "#undef");
235 lf_printf(file
, " ");
236 switch (what_to_do
) {
237 case get_values_from_icache
:
238 lf_printf(file
, "get-values-from-icache");
240 case put_values_in_icache
:
241 lf_printf(file
, "put-values-in-icache");
243 case both_values_and_icache
:
244 lf_printf(file
, "get-values-from-icache|put-values-in-icache");
246 case do_not_use_icache
:
247 lf_printf(file
, "do-not-use-icache");
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
) {
258 /* find any corresponding value */
259 for (bits
= expanded_bits
;
262 if (bits
->field
== cur_field
)
265 /* try the cache rule table for what to do */
267 cache_table
*cache_rule
;
268 for (cache_rule
= cache_rules
;
270 cache_rule
= cache_rule
->next
) {
271 if (strcmp(cur_field
->val_string
, cache_rule
->field_name
) == 0) {
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
,
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
,
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
,
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
,
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
,
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
,
318 ((what_to_do
& put_values_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 */
330 && ((what_to_declare
!= undef_variables
)
331 || !(what_to_do
& put_values_in_icache
)))
332 print_icache_extraction(file
,
334 cur_field
->val_string
,
335 NULL
, NULL
, NULL
, /* type, exp, orig */
336 instruction
->file_entry
->file_name
,
337 instruction
->file_entry
->line_nr
,
340 ((what_to_do
& put_values_in_icache
)
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
,
359 NULL
, 0, /* file_name & line_nr */
369 typedef struct _icache_tree icache_tree
;
370 struct _icache_tree
{
373 icache_tree
*children
;
377 icache_tree_insert(icache_tree
*tree
,
380 icache_tree
*new_tree
;
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 */
393 && strcmp(cur_tree
->name
, name
) == 0)
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
;
407 insn_table_cache_fields(insn_table
*table
)
409 icache_tree
*tree
= ZALLOC(icache_tree
);
411 for (instruction
= table
->insns
;
413 instruction
= instruction
->next
) {
416 icache_tree_insert(tree
,
417 instruction
->file_entry
->fields
[insn_form
]);
418 for (field
= instruction
->fields
->first
;
420 field
= field
->next
) {
421 if (field
->is_string
)
422 icache_tree_insert(form
, field
->val_string
);
431 print_icache_struct(insn_table
*instructions
,
432 cache_table
*cache_rules
,
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
)) {
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
;
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
;
458 field
= field
->next
) {
459 cache_table
*cache_rule
;
461 for (cache_rule
= cache_rules
;
463 cache_rule
= cache_rule
->next
) {
464 if (strcmp(field
->name
, cache_rule
->field_name
) == 0) {
466 if (cache_rule
->derived_name
!= NULL
)
467 lf_printf(file
, " %s %s; /* %s */\n",
468 (cache_rule
->type_def
== NULL
470 : cache_rule
->type_def
),
471 cache_rule
->derived_name
,
472 cache_rule
->field_name
);
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");
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");
494 print_icache_function(lf
*file
,
496 insn_bits
*expanded_bits
,
497 opcode_field
*opcodes
,
498 cache_table
*cache_rules
)
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
],
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");
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");
525 if ((code
& generate_with_semantic_icache
))
526 lf_printf(file
, "unsigned_word nia;\n");
527 print_icache_body(file
,
531 ((code
& generate_with_direct_access
)
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
],
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
,
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
],
563 function_name_prefix_semantics
);
564 lf_printf(file
, ";\n");
567 if ((code
& generate_with_direct_access
))
568 print_icache_body(file
,
573 ((code
& generate_with_semantic_icache
)
574 ? both_values_and_icache
575 : put_values_in_icache
));
578 lf_printf(file
, "}\n");
580 lf_printf(file
, "}\n");
585 print_icache_definition(insn_table
*entry
,
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
,
604 entry
->expanded_bits
,
609 print_icache_function(file
,
620 print_icache_internal_function_declaration(insn_table
*table
,
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",
630 print_function_name(file
,
631 function
->fields
[insn_name
],
633 function_name_prefix_icache
);
634 lf_printf(file
, "\n(%s);\n", ICACHE_FUNCTION_FORMAL
);
640 print_icache_internal_function_definition(insn_table
*table
,
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",
650 print_function_name(file
,
651 function
->fields
[insn_name
],
653 function_name_prefix_icache
);
654 lf_printf(file
, "\n(%s)\n", ICACHE_FUNCTION_FORMAL
);
655 lf_printf(file
, "{\n");
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");
665 lf_printf(file
, "return ");
666 print_function_name(file
,
667 function
->fields
[insn_name
],
669 function_name_prefix_semantics
);
670 lf_printf(file
, ";\n");
673 lf_print__internal_ref(file
);
675 lf_printf(file
, "}\n");