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/>.
27 #include "ld-decode.h"
33 #include "gen-semantics.h"
34 #include "gen-idecode.h"
35 #include "gen-icache.h"
40 print_icache_function_header(lf
*file
,
42 insn_bits
*expanded_bits
,
43 int is_function_definition
)
45 lf_printf(file
, "\n");
46 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "EXTERN_ICACHE", " ");
47 print_function_name(file
,
50 function_name_prefix_icache
);
51 lf_printf(file
, "\n(%s)", ICACHE_FUNCTION_FORMAL
);
52 if (!is_function_definition
)
54 lf_printf(file
, "\n");
59 print_icache_declaration(insn_table
*entry
,
65 if (generate_expanded_instructions
) {
66 ASSERT(entry
->nr_insn
== 1);
67 print_icache_function_header(file
,
68 entry
->insns
->file_entry
->fields
[insn_name
],
70 0/* is not function definition */);
73 print_icache_function_header(file
,
74 instruction
->file_entry
->fields
[insn_name
],
76 0/* is not function definition */);
83 print_icache_extraction(lf
*file
,
85 const char *entry_name
,
86 const char *entry_type
,
87 const char *entry_expression
,
88 const char *original_name
,
89 const char *file_name
,
91 insn_field
*cur_field
,
93 icache_decl_type what_to_declare
,
94 icache_body_type what_to_do
,
97 const char *expression
;
98 ASSERT(entry_name
!= NULL
);
100 /* Define a storage area for the cache element */
101 if (what_to_declare
== undef_variables
) {
102 /* We've finished with the value - destory it */
103 lf_indent_suppress(file
);
104 lf_printf(file
, "#undef %s\n", entry_name
);
107 else if (what_to_declare
== define_variables
) {
108 lf_indent_suppress(file
);
109 lf_printf(file
, "#define %s ", entry_name
);
112 if (file_name
!= NULL
)
113 lf_print__external_reference(file
, line_nr
, file_name
);
114 lf_printf(file
, "%s const %s UNUSED = ",
115 entry_type
== NULL
? "unsigned" : entry_type
,
119 /* define a value for that storage area as determined by what is in
122 && strcmp(entry_name
, cur_field
->val_string
) == 0
123 && ((bits
->opcode
->is_boolean
&& bits
->value
== 0)
124 || (!bits
->opcode
->is_boolean
))) {
125 /* The simple field has been made constant (as a result of
126 expanding instructions or similar). Remember that for a
127 boolean field, value is either 0 (implying the required
128 boolean_constant) or nonzero (implying some other value and
129 handled later below) - Define the variable accordingly */
130 expression
= "constant field";
131 ASSERT(bits
->field
== cur_field
);
132 ASSERT(entry_type
== NULL
);
133 if (bits
->opcode
->is_boolean
)
134 lf_printf(file
, "%d", bits
->opcode
->boolean_constant
);
135 else if (bits
->opcode
->last
< bits
->field
->last
)
136 lf_printf(file
, "%d",
137 bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
));
139 lf_printf(file
, "%d", bits
->value
);
141 else if (bits
!= NULL
142 && original_name
!= NULL
143 && strncmp(entry_name
,
144 original_name
, strlen(original_name
)) == 0
145 && strncmp(entry_name
+ strlen(original_name
),
146 "_is_", strlen("_is_")) == 0
147 && ((bits
->opcode
->is_boolean
148 && (atol(entry_name
+ strlen(original_name
) + strlen("_is_"))
149 == bits
->opcode
->boolean_constant
))
150 || (!bits
->opcode
->is_boolean
))) {
151 expression
= "constant compare";
152 /* An entry, derived from ORIGINAL_NAME, is testing to see of the
153 ORIGINAL_NAME has a specific constant value. That value
154 matching a boolean or constant field */
155 if (bits
->opcode
->is_boolean
)
156 lf_printf(file
, "%d /* %s == %d */",
159 bits
->opcode
->boolean_constant
);
160 else if (bits
->opcode
->last
< bits
->field
->last
)
161 lf_printf(file
, "%d /* %s == %d */",
162 (atol(entry_name
+ strlen(original_name
) + strlen("_is_"))
163 == (bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
))),
165 (bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
)));
167 lf_printf(file
, "%d /* %s == %d */",
168 (atol(entry_name
+ strlen(original_name
) + strlen("_is_"))
174 /* put the field in the local variable, possibly also enter it
176 expression
= "extraction";
177 /* handle the cache */
178 if ((what_to_do
& get_values_from_icache
)
179 || (what_to_do
& put_values_in_icache
)) {
180 lf_printf(file
, "cache_entry->crack.%s.%s",
181 instruction
->file_entry
->fields
[insn_form
],
183 if (what_to_do
& put_values_in_icache
) /* also put it in the cache? */
184 lf_printf(file
, " = ");
186 if ((what_to_do
& put_values_in_icache
)
187 || what_to_do
== do_not_use_icache
) {
188 if (cur_field
!= NULL
&& strcmp(entry_name
, cur_field
->val_string
) == 0)
189 lf_printf(file
, "EXTRACTED32(instruction, %d, %d)",
190 i2target(hi_bit_nr
, cur_field
->first
),
191 i2target(hi_bit_nr
, cur_field
->last
));
192 else if (entry_expression
!= NULL
)
193 lf_printf(file
, "%s", entry_expression
);
195 lf_printf(file
, "eval_%s", entry_name
);
199 if (!((what_to_declare
== define_variables
)
200 || (what_to_declare
== undef_variables
)))
201 lf_printf(file
, ";");
203 lf_printf(file
, " /* %s - %s */", reason
, expression
);
204 lf_printf(file
, "\n");
209 print_icache_body(lf
*file
,
211 insn_bits
*expanded_bits
,
212 cache_table
*cache_rules
,
213 icache_decl_type what_to_declare
,
214 icache_body_type what_to_do
)
216 insn_field
*cur_field
;
218 /* extract instruction fields */
219 lf_printf(file
, "/* extraction: %s ",
220 instruction
->file_entry
->fields
[insn_format
]);
221 switch (what_to_declare
) {
222 case define_variables
:
223 lf_printf(file
, "#define");
225 case declare_variables
:
226 lf_printf(file
, "declare");
228 case undef_variables
:
229 lf_printf(file
, "#undef");
232 lf_printf(file
, " ");
233 switch (what_to_do
) {
234 case get_values_from_icache
:
235 lf_printf(file
, "get-values-from-icache");
237 case put_values_in_icache
:
238 lf_printf(file
, "put-values-in-icache");
240 case both_values_and_icache
:
241 lf_printf(file
, "get-values-from-icache|put-values-in-icache");
243 case do_not_use_icache
:
244 lf_printf(file
, "do-not-use-icache");
247 lf_printf(file
, " */\n");
249 for (cur_field
= instruction
->fields
->first
;
250 cur_field
->first
< insn_bit_size
;
251 cur_field
= cur_field
->next
) {
252 if (cur_field
->is_string
) {
255 /* find any corresponding value */
256 for (bits
= expanded_bits
;
259 if (bits
->field
== cur_field
)
262 /* try the cache rule table for what to do */
264 cache_table
*cache_rule
;
265 for (cache_rule
= cache_rules
;
267 cache_rule
= cache_rule
->next
) {
268 if (strcmp(cur_field
->val_string
, cache_rule
->field_name
) == 0) {
270 if (cache_rule
->type
== scratch_value
271 && ((what_to_do
& put_values_in_icache
)
272 || what_to_do
== do_not_use_icache
))
273 print_icache_extraction(file
,
275 cache_rule
->derived_name
,
276 cache_rule
->type_def
,
277 cache_rule
->expression
,
278 cache_rule
->field_name
,
279 cache_rule
->file_entry
->file_name
,
280 cache_rule
->file_entry
->line_nr
,
286 else if (cache_rule
->type
== compute_value
287 && ((what_to_do
& get_values_from_icache
)
288 || what_to_do
== do_not_use_icache
))
289 print_icache_extraction(file
,
291 cache_rule
->derived_name
,
292 cache_rule
->type_def
,
293 cache_rule
->expression
,
294 cache_rule
->field_name
,
295 cache_rule
->file_entry
->file_name
,
296 cache_rule
->file_entry
->line_nr
,
302 else if (cache_rule
->type
== cache_value
303 && ((what_to_declare
!= undef_variables
)
304 || !(what_to_do
& put_values_in_icache
)))
305 print_icache_extraction(file
,
307 cache_rule
->derived_name
,
308 cache_rule
->type_def
,
309 cache_rule
->expression
,
310 cache_rule
->field_name
,
311 cache_rule
->file_entry
->file_name
,
312 cache_rule
->file_entry
->line_nr
,
315 ((what_to_do
& put_values_in_icache
)
323 /* No rule at all, assume that this is needed in the semantic
324 function (when values are extracted from the icache) and
325 hence must be put into the cache */
327 && ((what_to_declare
!= undef_variables
)
328 || !(what_to_do
& put_values_in_icache
)))
329 print_icache_extraction(file
,
331 cur_field
->val_string
,
332 NULL
, NULL
, NULL
, /* type, exp, orig */
333 instruction
->file_entry
->file_name
,
334 instruction
->file_entry
->line_nr
,
337 ((what_to_do
& put_values_in_icache
)
341 "default in icache");
342 /* any thing else ... */
346 lf_print__internal_reference(file
);
348 if ((code
& generate_with_insn_in_icache
)) {
349 lf_printf(file
, "\n");
350 print_icache_extraction(file
,
356 NULL
, 0, /* file_name & line_nr */
366 typedef struct _icache_tree icache_tree
;
367 struct _icache_tree
{
370 icache_tree
*children
;
374 icache_tree_insert(icache_tree
*tree
,
377 icache_tree
*new_tree
;
379 icache_tree
**ptr_to_cur_tree
= &tree
->children
;
380 icache_tree
*cur_tree
= *ptr_to_cur_tree
;
381 while (cur_tree
!= NULL
382 && strcmp(cur_tree
->name
, name
) < 0) {
383 ptr_to_cur_tree
= &cur_tree
->next
;
384 cur_tree
= *ptr_to_cur_tree
;
386 ASSERT(cur_tree
== NULL
387 || strcmp(cur_tree
->name
, name
) >= 0);
388 /* already in the tree */
390 && strcmp(cur_tree
->name
, name
) == 0)
392 /* missing, insert it */
393 ASSERT(cur_tree
== NULL
394 || strcmp(cur_tree
->name
, name
) > 0);
395 new_tree
= ZALLOC(icache_tree
);
396 new_tree
->name
= name
;
397 new_tree
->next
= cur_tree
;
398 *ptr_to_cur_tree
= new_tree
;
404 insn_table_cache_fields(insn_table
*table
)
406 icache_tree
*tree
= ZALLOC(icache_tree
);
408 for (instruction
= table
->insns
;
410 instruction
= instruction
->next
) {
413 icache_tree_insert(tree
,
414 instruction
->file_entry
->fields
[insn_form
]);
415 for (field
= instruction
->fields
->first
;
417 field
= field
->next
) {
418 if (field
->is_string
)
419 icache_tree_insert(form
, field
->val_string
);
428 print_icache_struct(insn_table
*instructions
,
429 cache_table
*cache_rules
,
432 icache_tree
*tree
= insn_table_cache_fields(instructions
);
434 lf_printf(file
, "\n");
435 lf_printf(file
, "#define WITH_IDECODE_CACHE_SIZE %d\n",
436 (code
& generate_with_icache
) ? icache_size
: 0);
437 lf_printf(file
, "\n");
439 /* create an instruction cache if being used */
440 if ((code
& generate_with_icache
)) {
442 lf_printf(file
, "typedef struct _idecode_cache {\n");
443 lf_printf(file
, " unsigned_word address;\n");
444 lf_printf(file
, " void *semantic;\n");
445 lf_printf(file
, " union {\n");
446 for (form
= tree
->children
;
450 lf_printf(file
, " struct {\n");
451 if (code
& generate_with_insn_in_icache
)
452 lf_printf(file
, " instruction_word insn;\n");
453 for (field
= form
->children
;
455 field
= field
->next
) {
456 cache_table
*cache_rule
;
458 for (cache_rule
= cache_rules
;
460 cache_rule
= cache_rule
->next
) {
461 if (strcmp(field
->name
, cache_rule
->field_name
) == 0) {
463 if (cache_rule
->derived_name
!= NULL
)
464 lf_printf(file
, " %s %s; /* %s */\n",
465 (cache_rule
->type_def
== NULL
467 : cache_rule
->type_def
),
468 cache_rule
->derived_name
,
469 cache_rule
->field_name
);
473 lf_printf(file
, " unsigned %s;\n", field
->name
);
475 lf_printf(file
, " } %s;\n", form
->name
);
477 lf_printf(file
, " } crack;\n");
478 lf_printf(file
, "} idecode_cache;\n");
481 /* alernativly, since no cache, emit a dummy definition for
482 idecode_cache so that code refering to the type can still compile */
483 lf_printf(file
, "typedef void idecode_cache;\n");
485 lf_printf(file
, "\n");
491 print_icache_function(lf
*file
,
493 insn_bits
*expanded_bits
,
494 opcode_field
*opcodes
,
495 cache_table
*cache_rules
)
499 /* generate code to enter decoded instruction into the icache */
500 lf_printf(file
, "\n");
501 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "EXTERN_ICACHE", "\n");
502 indent
= print_function_name(file
,
503 instruction
->file_entry
->fields
[insn_name
],
505 function_name_prefix_icache
);
506 lf_indent(file
, +indent
);
507 lf_printf(file
, "(%s)\n", ICACHE_FUNCTION_FORMAL
);
508 lf_indent(file
, -indent
);
510 /* function header */
511 lf_printf(file
, "{\n");
514 print_my_defines(file
, expanded_bits
, instruction
->file_entry
);
515 print_itrace(file
, instruction
->file_entry
, 1/*putting-value-in-cache*/);
517 print_idecode_validate(file
, instruction
, opcodes
);
519 lf_printf(file
, "\n");
520 lf_printf(file
, "{\n");
522 if ((code
& generate_with_semantic_icache
))
523 lf_printf(file
, "unsigned_word nia;\n");
524 print_icache_body(file
,
528 ((code
& generate_with_direct_access
)
530 : declare_variables
),
531 ((code
& generate_with_semantic_icache
)
532 ? both_values_and_icache
533 : put_values_in_icache
));
535 lf_printf(file
, "\n");
536 lf_printf(file
, "cache_entry->address = cia;\n");
537 lf_printf(file
, "cache_entry->semantic = ");
538 print_function_name(file
,
539 instruction
->file_entry
->fields
[insn_name
],
541 function_name_prefix_semantics
);
542 lf_printf(file
, ";\n");
543 lf_printf(file
, "\n");
545 if ((code
& generate_with_semantic_icache
)) {
546 lf_printf(file
, "/* semantic routine */\n");
547 print_semantic_body(file
,
551 lf_printf(file
, "return nia;\n");
554 if (!(code
& generate_with_semantic_icache
)) {
555 lf_printf(file
, "/* return the function proper */\n");
556 lf_printf(file
, "return ");
557 print_function_name(file
,
558 instruction
->file_entry
->fields
[insn_name
],
560 function_name_prefix_semantics
);
561 lf_printf(file
, ";\n");
564 if ((code
& generate_with_direct_access
))
565 print_icache_body(file
,
570 ((code
& generate_with_semantic_icache
)
571 ? both_values_and_icache
572 : put_values_in_icache
));
575 lf_printf(file
, "}\n");
577 lf_printf(file
, "}\n");
582 print_icache_definition(insn_table
*entry
,
588 cache_table
*cache_rules
= (cache_table
*)data
;
589 if (generate_expanded_instructions
) {
590 ASSERT(entry
->nr_insn
== 1
591 && entry
->opcode
== NULL
592 && entry
->parent
!= NULL
593 && entry
->parent
->opcode
!= NULL
);
594 ASSERT(entry
->nr_insn
== 1
595 && entry
->opcode
== NULL
596 && entry
->parent
!= NULL
597 && entry
->parent
->opcode
!= NULL
598 && entry
->parent
->opcode_rule
!= NULL
);
599 print_icache_function(file
,
601 entry
->expanded_bits
,
606 print_icache_function(file
,
617 print_icache_internal_function_declaration(insn_table
*table
,
620 table_entry
*function
)
622 ASSERT((code
& generate_with_icache
) != 0);
623 if (it_is("internal", function
->fields
[insn_flags
])) {
624 lf_printf(file
, "\n");
625 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "PSIM_INLINE_ICACHE",
627 print_function_name(file
,
628 function
->fields
[insn_name
],
630 function_name_prefix_icache
);
631 lf_printf(file
, "\n(%s);\n", ICACHE_FUNCTION_FORMAL
);
637 print_icache_internal_function_definition(insn_table
*table
,
640 table_entry
*function
)
642 ASSERT((code
& generate_with_icache
) != 0);
643 if (it_is("internal", function
->fields
[insn_flags
])) {
644 lf_printf(file
, "\n");
645 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "PSIM_INLINE_ICACHE",
647 print_function_name(file
,
648 function
->fields
[insn_name
],
650 function_name_prefix_icache
);
651 lf_printf(file
, "\n(%s)\n", ICACHE_FUNCTION_FORMAL
);
652 lf_printf(file
, "{\n");
654 lf_printf(file
, "/* semantic routine */\n");
655 table_entry_print_cpp_line_nr(file
, function
);
656 if ((code
& generate_with_semantic_icache
)) {
657 lf_print__c_code(file
, function
->annex
);
658 lf_printf(file
, "error(\"Internal function must longjump\\n\");\n");
659 lf_printf(file
, "return 0;\n");
662 lf_printf(file
, "return ");
663 print_function_name(file
,
664 function
->fields
[insn_name
],
666 function_name_prefix_semantics
);
667 lf_printf(file
, ";\n");
670 lf_print__internal_reference(file
);
672 lf_printf(file
, "}\n");