1 /* This file is part of the program psim.
3 Copyright (C) 1994-1995, 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
)
97 ASSERT(entry_name
!= NULL
);
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
);
106 else if (what_to_declare
== define_variables
) {
107 lf_indent_suppress(file
);
108 lf_printf(file
, "#define %s ", entry_name
);
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
,
118 /* define a value for that storage area as determined by what is in
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
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
));
137 lf_printf(file
, "%d", bits
->value
);
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
);
155 /* put the field in the local variable, possibly also enter it
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
],
163 if (what_to_do
& put_values_in_icache
) /* also put it in the cache? */
164 lf_printf(file
, " = ");
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
);
175 lf_printf(file
, "eval_%s", entry_name
);
179 if ((what_to_declare
== define_variables
)
180 || (what_to_declare
== undef_variables
))
181 lf_printf(file
, "\n");
183 lf_printf(file
, ";\n");
188 print_icache_body(lf
*file
,
190 insn_bits
*expanded_bits
,
191 cache_table
*cache_rules
,
192 icache_decl_type what_to_declare
,
193 icache_body_type what_to_do
)
195 insn_field
*cur_field
;
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");
204 case declare_variables
:
205 lf_printf(file
, "declare");
207 case undef_variables
:
208 lf_printf(file
, "#undef");
211 lf_printf(file
, " ");
212 switch (what_to_do
) {
213 case get_values_from_icache
:
214 lf_printf(file
, "get-values-from-icache");
216 case put_values_in_icache
:
217 lf_printf(file
, "put-values-in-icache");
219 case both_values_and_icache
:
220 lf_printf(file
, "get-values-from-icache|put-values-in-icache");
222 case do_not_use_icache
:
223 lf_printf(file
, "do-not-use-icache");
226 lf_printf(file
, " */\n");
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
) {
234 /* find any corresponding value */
235 for (bits
= expanded_bits
;
238 if (bits
->field
== cur_field
)
241 /* try the cache rule table for what to do */
243 cache_table
*cache_rule
;
244 for (cache_rule
= cache_rules
;
246 cache_rule
= cache_rule
->next
) {
247 if (strcmp(cur_field
->val_string
, cache_rule
->field_name
) == 0) {
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
,
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
,
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
,
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
,
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
,
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
,
292 ((what_to_do
& put_values_in_icache
)
299 /* No rule at all, assume that it should go into the cache */
301 && ((what_to_declare
!= undef_variables
)
302 || !(what_to_do
& put_values_in_icache
)))
303 print_icache_extraction(file
,
305 cur_field
->val_string
,
306 NULL
, NULL
, NULL
, /* type, exp, orig */
307 instruction
->file_entry
->file_name
,
308 instruction
->file_entry
->line_nr
,
311 ((what_to_do
& put_values_in_icache
)
315 /* any thing else ... */
319 lf_print__internal_reference(file
);
321 if ((code
& generate_with_insn_in_icache
)) {
322 lf_printf(file
, "\n");
323 print_icache_extraction(file
,
329 NULL
, 0, /* file_name & line_nr */
338 typedef struct _icache_tree icache_tree
;
339 struct _icache_tree
{
342 icache_tree
*children
;
346 icache_tree_insert(icache_tree
*tree
,
349 icache_tree
*new_tree
;
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
;
358 ASSERT(cur_tree
== NULL
359 || strcmp(cur_tree
->name
, name
) >= 0);
360 /* already in the tree */
362 && strcmp(cur_tree
->name
, name
) == 0)
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
;
376 insn_table_cache_fields(insn_table
*table
)
378 icache_tree
*tree
= ZALLOC(icache_tree
);
380 for (instruction
= table
->insns
;
382 instruction
= instruction
->next
) {
385 icache_tree_insert(tree
,
386 instruction
->file_entry
->fields
[insn_form
]);
387 for (field
= instruction
->fields
->first
;
389 field
= field
->next
) {
390 if (field
->is_string
)
391 icache_tree_insert(form
, field
->val_string
);
400 print_icache_struct(insn_table
*instructions
,
401 cache_table
*cache_rules
,
404 icache_tree
*tree
= insn_table_cache_fields(instructions
);
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");
411 /* create an instruction cache if being used */
412 if ((code
& generate_with_icache
)) {
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
;
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
;
427 field
= field
->next
) {
428 cache_table
*cache_rule
;
430 for (cache_rule
= cache_rules
;
432 cache_rule
= cache_rule
->next
) {
433 if (strcmp(field
->name
, cache_rule
->field_name
) == 0) {
435 if (cache_rule
->derived_name
!= NULL
)
436 lf_printf(file
, " %s %s; /* %s */\n",
437 (cache_rule
->type_def
== NULL
439 : cache_rule
->type_def
),
440 cache_rule
->derived_name
,
441 cache_rule
->field_name
);
445 lf_printf(file
, " unsigned %s;\n", field
->name
);
447 lf_printf(file
, " } %s;\n", form
->name
);
449 lf_printf(file
, " } crack;\n");
450 lf_printf(file
, "} idecode_cache;\n");
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");
457 lf_printf(file
, "\n");
463 print_icache_function(lf
*file
,
465 insn_bits
*expanded_bits
,
466 opcode_field
*opcodes
,
467 cache_table
*cache_rules
)
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
],
477 function_name_prefix_icache
);
478 lf_indent(file
, +indent
);
479 lf_printf(file
, "(%s)\n", ICACHE_FUNCTION_FORMAL
);
480 lf_indent(file
, -indent
);
482 /* function header */
483 lf_printf(file
, "{\n");
486 print_my_defines(file
, expanded_bits
, instruction
->file_entry
);
487 print_itrace(file
, instruction
->file_entry
, 1/*putting-value-in-cache*/);
489 print_idecode_validate(file
, instruction
, opcodes
);
491 lf_printf(file
, "\n");
492 lf_printf(file
, "{\n");
494 if ((code
& generate_with_semantic_icache
))
495 lf_printf(file
, "unsigned_word nia;\n");
496 print_icache_body(file
,
500 ((code
& generate_with_direct_access
)
502 : declare_variables
),
503 ((code
& generate_with_semantic_icache
)
504 ? both_values_and_icache
505 : put_values_in_icache
));
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
],
513 function_name_prefix_semantics
);
514 lf_printf(file
, ";\n");
515 lf_printf(file
, "\n");
517 if ((code
& generate_with_semantic_icache
)) {
518 lf_printf(file
, "/* semantic routine */\n");
519 print_semantic_body(file
,
523 lf_printf(file
, "return nia;\n");
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
],
532 function_name_prefix_semantics
);
533 lf_printf(file
, ";\n");
536 if ((code
& generate_with_direct_access
))
537 print_icache_body(file
,
542 ((code
& generate_with_semantic_icache
)
543 ? both_values_and_icache
544 : put_values_in_icache
));
547 lf_printf(file
, "}\n");
549 lf_printf(file
, "}\n");
554 print_icache_definition(insn_table
*entry
,
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
,
573 entry
->expanded_bits
,
578 print_icache_function(file
,
589 print_icache_internal_function_declaration(insn_table
*table
,
592 table_entry
*function
)
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",
599 print_function_name(file
,
600 function
->fields
[insn_name
],
602 function_name_prefix_icache
);
603 lf_printf(file
, "\n(%s);\n", ICACHE_FUNCTION_FORMAL
);
609 print_icache_internal_function_definition(insn_table
*table
,
612 table_entry
*function
)
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",
619 print_function_name(file
,
620 function
->fields
[insn_name
],
622 function_name_prefix_icache
);
623 lf_printf(file
, "\n(%s)\n", ICACHE_FUNCTION_FORMAL
);
624 lf_printf(file
, "{\n");
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");
634 lf_printf(file
, "return ");
635 print_function_name(file
,
636 function
->fields
[insn_name
],
638 function_name_prefix_semantics
);
639 lf_printf(file
, ";\n");
642 lf_print__internal_reference(file
);
644 lf_printf(file
, "}\n");