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 2 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include "ld-decode.h"
34 #include "gen-semantics.h"
35 #include "gen-idecode.h"
36 #include "gen-icache.h"
41 print_icache_function_header(lf
*file
,
43 insn_bits
*expanded_bits
,
44 int is_function_definition
)
46 lf_printf(file
, "\n");
47 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "EXTERN_ICACHE", " ");
48 print_function_name(file
,
51 function_name_prefix_icache
);
52 lf_printf(file
, "\n(%s)", ICACHE_FUNCTION_FORMAL
);
53 if (!is_function_definition
)
55 lf_printf(file
, "\n");
60 print_icache_declaration(insn_table
*entry
,
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
],
71 0/* is not function definition */);
74 print_icache_function_header(file
,
75 instruction
->file_entry
->fields
[insn_name
],
77 0/* is not function definition */);
84 print_icache_extraction(lf
*file
,
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
,
92 insn_field
*cur_field
,
94 icache_decl_type what_to_declare
,
95 icache_body_type what_to_do
,
98 const char *expression
;
99 ASSERT(entry_name
!= NULL
);
101 /* Define a storage area for the cache element */
102 if (what_to_declare
== undef_variables
) {
103 /* We've finished with the value - destory it */
104 lf_indent_suppress(file
);
105 lf_printf(file
, "#undef %s\n", entry_name
);
108 else if (what_to_declare
== define_variables
) {
109 lf_indent_suppress(file
);
110 lf_printf(file
, "#define %s ", entry_name
);
113 if (file_name
!= NULL
)
114 lf_print__external_reference(file
, line_nr
, file_name
);
115 lf_printf(file
, "%s const %s UNUSED = ",
116 entry_type
== NULL
? "unsigned" : entry_type
,
120 /* define a value for that storage area as determined by what is in
123 && strcmp(entry_name
, cur_field
->val_string
) == 0
124 && ((bits
->opcode
->is_boolean
&& bits
->value
== 0)
125 || (!bits
->opcode
->is_boolean
))) {
126 /* The simple field has been made constant (as a result of
127 expanding instructions or similar). Remember that for a
128 boolean field, value is either 0 (implying the required
129 boolean_constant) or nonzero (implying some other value and
130 handled later below) - Define the variable accordingly */
131 expression
= "constant field";
132 ASSERT(bits
->field
== cur_field
);
133 ASSERT(entry_type
== NULL
);
134 if (bits
->opcode
->is_boolean
)
135 lf_printf(file
, "%d", bits
->opcode
->boolean_constant
);
136 else if (bits
->opcode
->last
< bits
->field
->last
)
137 lf_printf(file
, "%d",
138 bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
));
140 lf_printf(file
, "%d", bits
->value
);
142 else if (bits
!= NULL
143 && original_name
!= NULL
144 && strncmp(entry_name
,
145 original_name
, strlen(original_name
)) == 0
146 && strncmp(entry_name
+ strlen(original_name
),
147 "_is_", strlen("_is_")) == 0
148 && ((bits
->opcode
->is_boolean
149 && (atol(entry_name
+ strlen(original_name
) + strlen("_is_"))
150 == bits
->opcode
->boolean_constant
))
151 || (!bits
->opcode
->is_boolean
))) {
152 expression
= "constant compare";
153 /* An entry, derived from ORIGINAL_NAME, is testing to see of the
154 ORIGINAL_NAME has a specific constant value. That value
155 matching a boolean or constant field */
156 if (bits
->opcode
->is_boolean
)
157 lf_printf(file
, "%d /* %s == %d */",
160 bits
->opcode
->boolean_constant
);
161 else if (bits
->opcode
->last
< bits
->field
->last
)
162 lf_printf(file
, "%d /* %s == %d */",
163 (atol(entry_name
+ strlen(original_name
) + strlen("_is_"))
164 == (bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
))),
166 (bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
)));
168 lf_printf(file
, "%d /* %s == %d */",
169 (atol(entry_name
+ strlen(original_name
) + strlen("_is_"))
175 /* put the field in the local variable, possibly also enter it
177 expression
= "extraction";
178 /* handle the cache */
179 if ((what_to_do
& get_values_from_icache
)
180 || (what_to_do
& put_values_in_icache
)) {
181 lf_printf(file
, "cache_entry->crack.%s.%s",
182 instruction
->file_entry
->fields
[insn_form
],
184 if (what_to_do
& put_values_in_icache
) /* also put it in the cache? */
185 lf_printf(file
, " = ");
187 if ((what_to_do
& put_values_in_icache
)
188 || what_to_do
== do_not_use_icache
) {
189 if (cur_field
!= NULL
&& strcmp(entry_name
, cur_field
->val_string
) == 0)
190 lf_printf(file
, "EXTRACTED32(instruction, %d, %d)",
191 i2target(hi_bit_nr
, cur_field
->first
),
192 i2target(hi_bit_nr
, cur_field
->last
));
193 else if (entry_expression
!= NULL
)
194 lf_printf(file
, "%s", entry_expression
);
196 lf_printf(file
, "eval_%s", entry_name
);
200 if (!((what_to_declare
== define_variables
)
201 || (what_to_declare
== undef_variables
)))
202 lf_printf(file
, ";");
204 lf_printf(file
, " /* %s - %s */", reason
, expression
);
205 lf_printf(file
, "\n");
210 print_icache_body(lf
*file
,
212 insn_bits
*expanded_bits
,
213 cache_table
*cache_rules
,
214 icache_decl_type what_to_declare
,
215 icache_body_type what_to_do
)
217 insn_field
*cur_field
;
219 /* extract instruction fields */
220 lf_printf(file
, "/* extraction: %s ",
221 instruction
->file_entry
->fields
[insn_format
]);
222 switch (what_to_declare
) {
223 case define_variables
:
224 lf_printf(file
, "#define");
226 case declare_variables
:
227 lf_printf(file
, "declare");
229 case undef_variables
:
230 lf_printf(file
, "#undef");
233 lf_printf(file
, " ");
234 switch (what_to_do
) {
235 case get_values_from_icache
:
236 lf_printf(file
, "get-values-from-icache");
238 case put_values_in_icache
:
239 lf_printf(file
, "put-values-in-icache");
241 case both_values_and_icache
:
242 lf_printf(file
, "get-values-from-icache|put-values-in-icache");
244 case do_not_use_icache
:
245 lf_printf(file
, "do-not-use-icache");
248 lf_printf(file
, " */\n");
250 for (cur_field
= instruction
->fields
->first
;
251 cur_field
->first
< insn_bit_size
;
252 cur_field
= cur_field
->next
) {
253 if (cur_field
->is_string
) {
256 /* find any corresponding value */
257 for (bits
= expanded_bits
;
260 if (bits
->field
== cur_field
)
263 /* try the cache rule table for what to do */
265 cache_table
*cache_rule
;
266 for (cache_rule
= cache_rules
;
268 cache_rule
= cache_rule
->next
) {
269 if (strcmp(cur_field
->val_string
, cache_rule
->field_name
) == 0) {
271 if (cache_rule
->type
== scratch_value
272 && ((what_to_do
& put_values_in_icache
)
273 || what_to_do
== do_not_use_icache
))
274 print_icache_extraction(file
,
276 cache_rule
->derived_name
,
277 cache_rule
->type_def
,
278 cache_rule
->expression
,
279 cache_rule
->field_name
,
280 cache_rule
->file_entry
->file_name
,
281 cache_rule
->file_entry
->line_nr
,
287 else if (cache_rule
->type
== compute_value
288 && ((what_to_do
& get_values_from_icache
)
289 || what_to_do
== do_not_use_icache
))
290 print_icache_extraction(file
,
292 cache_rule
->derived_name
,
293 cache_rule
->type_def
,
294 cache_rule
->expression
,
295 cache_rule
->field_name
,
296 cache_rule
->file_entry
->file_name
,
297 cache_rule
->file_entry
->line_nr
,
303 else if (cache_rule
->type
== cache_value
304 && ((what_to_declare
!= undef_variables
)
305 || !(what_to_do
& put_values_in_icache
)))
306 print_icache_extraction(file
,
308 cache_rule
->derived_name
,
309 cache_rule
->type_def
,
310 cache_rule
->expression
,
311 cache_rule
->field_name
,
312 cache_rule
->file_entry
->file_name
,
313 cache_rule
->file_entry
->line_nr
,
316 ((what_to_do
& put_values_in_icache
)
324 /* No rule at all, assume that this is needed in the semantic
325 function (when values are extracted from the icache) and
326 hence must be put into the cache */
328 && ((what_to_declare
!= undef_variables
)
329 || !(what_to_do
& put_values_in_icache
)))
330 print_icache_extraction(file
,
332 cur_field
->val_string
,
333 NULL
, NULL
, NULL
, /* type, exp, orig */
334 instruction
->file_entry
->file_name
,
335 instruction
->file_entry
->line_nr
,
338 ((what_to_do
& put_values_in_icache
)
342 "default in icache");
343 /* any thing else ... */
347 lf_print__internal_reference(file
);
349 if ((code
& generate_with_insn_in_icache
)) {
350 lf_printf(file
, "\n");
351 print_icache_extraction(file
,
357 NULL
, 0, /* file_name & line_nr */
367 typedef struct _icache_tree icache_tree
;
368 struct _icache_tree
{
371 icache_tree
*children
;
375 icache_tree_insert(icache_tree
*tree
,
378 icache_tree
*new_tree
;
380 icache_tree
**ptr_to_cur_tree
= &tree
->children
;
381 icache_tree
*cur_tree
= *ptr_to_cur_tree
;
382 while (cur_tree
!= NULL
383 && strcmp(cur_tree
->name
, name
) < 0) {
384 ptr_to_cur_tree
= &cur_tree
->next
;
385 cur_tree
= *ptr_to_cur_tree
;
387 ASSERT(cur_tree
== NULL
388 || strcmp(cur_tree
->name
, name
) >= 0);
389 /* already in the tree */
391 && strcmp(cur_tree
->name
, name
) == 0)
393 /* missing, insert it */
394 ASSERT(cur_tree
== NULL
395 || strcmp(cur_tree
->name
, name
) > 0);
396 new_tree
= ZALLOC(icache_tree
);
397 new_tree
->name
= name
;
398 new_tree
->next
= cur_tree
;
399 *ptr_to_cur_tree
= new_tree
;
405 insn_table_cache_fields(insn_table
*table
)
407 icache_tree
*tree
= ZALLOC(icache_tree
);
409 for (instruction
= table
->insns
;
411 instruction
= instruction
->next
) {
414 icache_tree_insert(tree
,
415 instruction
->file_entry
->fields
[insn_form
]);
416 for (field
= instruction
->fields
->first
;
418 field
= field
->next
) {
419 if (field
->is_string
)
420 icache_tree_insert(form
, field
->val_string
);
429 print_icache_struct(insn_table
*instructions
,
430 cache_table
*cache_rules
,
433 icache_tree
*tree
= insn_table_cache_fields(instructions
);
435 lf_printf(file
, "\n");
436 lf_printf(file
, "#define WITH_IDECODE_CACHE_SIZE %d\n",
437 (code
& generate_with_icache
) ? icache_size
: 0);
438 lf_printf(file
, "\n");
440 /* create an instruction cache if being used */
441 if ((code
& generate_with_icache
)) {
443 lf_printf(file
, "typedef struct _idecode_cache {\n");
444 lf_printf(file
, " unsigned_word address;\n");
445 lf_printf(file
, " void *semantic;\n");
446 lf_printf(file
, " union {\n");
447 for (form
= tree
->children
;
451 lf_printf(file
, " struct {\n");
452 if (code
& generate_with_insn_in_icache
)
453 lf_printf(file
, " instruction_word insn;\n");
454 for (field
= form
->children
;
456 field
= field
->next
) {
457 cache_table
*cache_rule
;
459 for (cache_rule
= cache_rules
;
461 cache_rule
= cache_rule
->next
) {
462 if (strcmp(field
->name
, cache_rule
->field_name
) == 0) {
464 if (cache_rule
->derived_name
!= NULL
)
465 lf_printf(file
, " %s %s; /* %s */\n",
466 (cache_rule
->type_def
== NULL
468 : cache_rule
->type_def
),
469 cache_rule
->derived_name
,
470 cache_rule
->field_name
);
474 lf_printf(file
, " unsigned %s;\n", field
->name
);
476 lf_printf(file
, " } %s;\n", form
->name
);
478 lf_printf(file
, " } crack;\n");
479 lf_printf(file
, "} idecode_cache;\n");
482 /* alernativly, since no cache, emit a dummy definition for
483 idecode_cache so that code refering to the type can still compile */
484 lf_printf(file
, "typedef void idecode_cache;\n");
486 lf_printf(file
, "\n");
492 print_icache_function(lf
*file
,
494 insn_bits
*expanded_bits
,
495 opcode_field
*opcodes
,
496 cache_table
*cache_rules
)
500 /* generate code to enter decoded instruction into the icache */
501 lf_printf(file
, "\n");
502 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "EXTERN_ICACHE", "\n");
503 indent
= print_function_name(file
,
504 instruction
->file_entry
->fields
[insn_name
],
506 function_name_prefix_icache
);
507 lf_indent(file
, +indent
);
508 lf_printf(file
, "(%s)\n", ICACHE_FUNCTION_FORMAL
);
509 lf_indent(file
, -indent
);
511 /* function header */
512 lf_printf(file
, "{\n");
515 print_my_defines(file
, expanded_bits
, instruction
->file_entry
);
516 print_itrace(file
, instruction
->file_entry
, 1/*putting-value-in-cache*/);
518 print_idecode_validate(file
, instruction
, opcodes
);
520 lf_printf(file
, "\n");
521 lf_printf(file
, "{\n");
523 if ((code
& generate_with_semantic_icache
))
524 lf_printf(file
, "unsigned_word nia;\n");
525 print_icache_body(file
,
529 ((code
& generate_with_direct_access
)
531 : declare_variables
),
532 ((code
& generate_with_semantic_icache
)
533 ? both_values_and_icache
534 : put_values_in_icache
));
536 lf_printf(file
, "\n");
537 lf_printf(file
, "cache_entry->address = cia;\n");
538 lf_printf(file
, "cache_entry->semantic = ");
539 print_function_name(file
,
540 instruction
->file_entry
->fields
[insn_name
],
542 function_name_prefix_semantics
);
543 lf_printf(file
, ";\n");
544 lf_printf(file
, "\n");
546 if ((code
& generate_with_semantic_icache
)) {
547 lf_printf(file
, "/* semantic routine */\n");
548 print_semantic_body(file
,
552 lf_printf(file
, "return nia;\n");
555 if (!(code
& generate_with_semantic_icache
)) {
556 lf_printf(file
, "/* return the function proper */\n");
557 lf_printf(file
, "return ");
558 print_function_name(file
,
559 instruction
->file_entry
->fields
[insn_name
],
561 function_name_prefix_semantics
);
562 lf_printf(file
, ";\n");
565 if ((code
& generate_with_direct_access
))
566 print_icache_body(file
,
571 ((code
& generate_with_semantic_icache
)
572 ? both_values_and_icache
573 : put_values_in_icache
));
576 lf_printf(file
, "}\n");
578 lf_printf(file
, "}\n");
583 print_icache_definition(insn_table
*entry
,
589 cache_table
*cache_rules
= (cache_table
*)data
;
590 if (generate_expanded_instructions
) {
591 ASSERT(entry
->nr_insn
== 1
592 && entry
->opcode
== NULL
593 && entry
->parent
!= NULL
594 && entry
->parent
->opcode
!= NULL
);
595 ASSERT(entry
->nr_insn
== 1
596 && entry
->opcode
== NULL
597 && entry
->parent
!= NULL
598 && entry
->parent
->opcode
!= NULL
599 && entry
->parent
->opcode_rule
!= NULL
);
600 print_icache_function(file
,
602 entry
->expanded_bits
,
607 print_icache_function(file
,
618 print_icache_internal_function_declaration(insn_table
*table
,
621 table_entry
*function
)
623 ASSERT((code
& generate_with_icache
) != 0);
624 if (it_is("internal", function
->fields
[insn_flags
])) {
625 lf_printf(file
, "\n");
626 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "INLINE_ICACHE",
628 print_function_name(file
,
629 function
->fields
[insn_name
],
631 function_name_prefix_icache
);
632 lf_printf(file
, "\n(%s);\n", ICACHE_FUNCTION_FORMAL
);
638 print_icache_internal_function_definition(insn_table
*table
,
641 table_entry
*function
)
643 ASSERT((code
& generate_with_icache
) != 0);
644 if (it_is("internal", function
->fields
[insn_flags
])) {
645 lf_printf(file
, "\n");
646 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "INLINE_ICACHE",
648 print_function_name(file
,
649 function
->fields
[insn_name
],
651 function_name_prefix_icache
);
652 lf_printf(file
, "\n(%s)\n", ICACHE_FUNCTION_FORMAL
);
653 lf_printf(file
, "{\n");
655 lf_printf(file
, "/* semantic routine */\n");
656 table_entry_print_cpp_line_nr(file
, function
);
657 if ((code
& generate_with_semantic_icache
)) {
658 lf_print__c_code(file
, function
->annex
);
659 lf_printf(file
, "error(\"Internal function must longjump\\n\");\n");
660 lf_printf(file
, "return 0;\n");
663 lf_printf(file
, "return ");
664 print_function_name(file
,
665 function
->fields
[insn_name
],
667 function_name_prefix_semantics
);
668 lf_printf(file
, ";\n");
671 lf_print__internal_reference(file
);
673 lf_printf(file
, "}\n");