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
,
88 char *field_expression
,
89 const char *file_name
,
91 insn_field
*cur_field
,
94 int get_value_from_cache
,
95 int put_value_in_cache
)
97 ASSERT(field_name
!= NULL
);
98 if (use_defines
&& put_value_in_cache
) {
99 /* We've finished with the value - destory it */
100 lf_indent_suppress(file
);
101 lf_printf(file
, "#undef %s\n", field_name
);
104 else if (use_defines
&& get_value_from_cache
) {
105 lf_indent_suppress(file
);
106 lf_printf(file
, "#define %s ", field_name
);
109 lf_print__external_reference(file
, line_nr
, file_name
);
110 lf_printf(file
, "%s const %s __attribute__((__unused__)) = ",
111 field_type
== NULL
? "unsigned" : field_type
,
116 && ((bits
->opcode
->is_boolean
118 || !bits
->opcode
->is_boolean
)
119 && strcmp(field_name
, cur_field
->val_string
) == 0) {
120 /* The field has been made constant (as a result of expanding
121 instructions or similar) - define a constant variable with the
122 corresponding value. */
123 ASSERT(bits
->field
== cur_field
);
124 ASSERT(field_type
== NULL
);
125 if (bits
->opcode
->is_boolean
)
126 lf_printf(file
, "%d", bits
->opcode
->boolean_constant
);
127 else if (bits
->opcode
->last
< bits
->field
->last
)
128 lf_printf(file
, "%d",
129 bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
));
131 lf_printf(file
, "%d", bits
->value
);
134 /* put the field in the local variable, possibly also enter it
136 /* getting it from the cache */
137 if (get_value_from_cache
|| put_value_in_cache
) {
138 lf_printf(file
, "cache_entry->crack.%s.%s",
139 instruction
->file_entry
->fields
[insn_form
],
141 if (put_value_in_cache
) /* also put it in the cache? */
142 lf_printf(file
, " = ");
144 if (!get_value_from_cache
) {
145 if (strcmp(field_name
, cur_field
->val_string
) == 0)
146 lf_printf(file
, "EXTRACTED32(instruction, %d, %d)",
147 i2target(hi_bit_nr
, cur_field
->first
),
148 i2target(hi_bit_nr
, cur_field
->last
));
149 else if (field_expression
!= NULL
)
150 lf_printf(file
, "%s", field_expression
);
152 lf_printf(file
, "eval_%s", field_name
);
156 if (use_defines
&& get_value_from_cache
)
157 lf_printf(file
, "\n");
159 lf_printf(file
, ";\n");
164 print_icache_body(lf
*file
,
166 insn_bits
*expanded_bits
,
167 cache_table
*cache_rules
,
169 int get_value_from_cache
,
170 int put_value_in_cache
)
172 insn_field
*cur_field
;
174 /* extract instruction fields */
175 lf_printf(file
, "/* extraction: %s defines=%d get-value=%d put-value=%d */\n",
176 instruction
->file_entry
->fields
[insn_format
],
177 use_defines
, get_value_from_cache
, put_value_in_cache
);
179 for (cur_field
= instruction
->fields
->first
;
180 cur_field
->first
< insn_bit_size
;
181 cur_field
= cur_field
->next
) {
182 if (cur_field
->is_string
) {
185 /* find any corresponding value */
186 for (bits
= expanded_bits
;
189 if (bits
->field
== cur_field
)
192 /* try the cache rule table for what to do */
193 if (get_value_from_cache
|| put_value_in_cache
) {
194 cache_table
*cache_rule
;
195 for (cache_rule
= cache_rules
;
197 cache_rule
= cache_rule
->next
) {
198 if (strcmp(cur_field
->val_string
, cache_rule
->old_name
) == 0) {
200 if (cache_rule
->type
== compute_value
201 && put_value_in_cache
203 print_icache_extraction(file
,
205 cache_rule
->new_name
,
206 cache_rule
->type_def
,
207 cache_rule
->expression
,
208 cache_rule
->file_entry
->file_name
,
209 cache_rule
->file_entry
->line_nr
,
213 0 /*get-value-from-cache*/,
214 0 /*put-value-in-cache*/);
215 else if (cache_rule
->type
== cache_value
)
216 print_icache_extraction(file
,
218 cache_rule
->new_name
,
219 cache_rule
->type_def
,
220 cache_rule
->expression
,
221 cache_rule
->file_entry
->file_name
,
222 cache_rule
->file_entry
->line_nr
,
226 get_value_from_cache
,
232 print_icache_extraction(file
,
234 cur_field
->val_string
,
237 instruction
->file_entry
->file_name
,
238 instruction
->file_entry
->line_nr
,
242 get_value_from_cache
,
244 /* if any (XXX == 0), output a corresponding test */
245 if (instruction
->file_entry
->annex
!= NULL
) {
246 char *field_name
= cur_field
->val_string
;
247 char *is_0_ptr
= instruction
->file_entry
->annex
;
248 int field_len
= strlen(field_name
);
249 if (strlen(is_0_ptr
) >= (strlen("_is_0") + field_len
)) {
250 is_0_ptr
+= field_len
;
251 while ((is_0_ptr
= strstr(is_0_ptr
, "_is_0")) != NULL
) {
252 if (strncmp(is_0_ptr
- field_len
, field_name
, field_len
) == 0
253 && !isalpha(is_0_ptr
[ - field_len
- 1])) {
254 if (!use_defines
|| (use_defines
&& get_value_from_cache
)) {
256 lf_indent_suppress(file
);
257 lf_printf(file
, "#define %s_is_0 ", field_name
);
260 table_entry_print_cpp_line_nr(file
, instruction
->file_entry
);
261 lf_printf(file
, "const unsigned %s_is_0 __attribute__((__unused__)) = ",
265 lf_printf(file
, "(%d == 0)", bits
->value
);
267 lf_printf(file
, "(%s == 0)", field_name
);
269 lf_printf(file
, "\n");
271 lf_printf(file
, ";\n");
273 else if (use_defines
&& put_value_in_cache
) {
274 lf_indent_suppress(file
);
275 lf_printf(file
, "#undef %s_is_0\n", field_name
);
279 is_0_ptr
+= strlen("_is_0");
283 /* any thing else ... */
286 lf_print__internal_reference(file
);
291 typedef struct _icache_tree icache_tree
;
292 struct _icache_tree
{
295 icache_tree
*children
;
299 icache_tree_insert(icache_tree
*tree
,
302 icache_tree
*new_tree
;
304 icache_tree
**ptr_to_cur_tree
= &tree
->children
;
305 icache_tree
*cur_tree
= *ptr_to_cur_tree
;
306 while (cur_tree
!= NULL
307 && strcmp(cur_tree
->name
, name
) < 0) {
308 ptr_to_cur_tree
= &cur_tree
->next
;
309 cur_tree
= *ptr_to_cur_tree
;
311 ASSERT(cur_tree
== NULL
312 || strcmp(cur_tree
->name
, name
) >= 0);
313 /* already in the tree */
315 && strcmp(cur_tree
->name
, name
) == 0)
317 /* missing, insert it */
318 ASSERT(cur_tree
== NULL
319 || strcmp(cur_tree
->name
, name
) > 0);
320 new_tree
= ZALLOC(icache_tree
);
321 new_tree
->name
= name
;
322 new_tree
->next
= cur_tree
;
323 *ptr_to_cur_tree
= new_tree
;
329 insn_table_cache_fields(insn_table
*table
)
331 icache_tree
*tree
= ZALLOC(icache_tree
);
333 for (instruction
= table
->insns
;
335 instruction
= instruction
->next
) {
338 icache_tree_insert(tree
,
339 instruction
->file_entry
->fields
[insn_form
]);
340 for (field
= instruction
->fields
->first
;
342 field
= field
->next
) {
343 if (field
->is_string
)
344 icache_tree_insert(form
, field
->val_string
);
353 print_icache_struct(insn_table
*instructions
,
354 cache_table
*cache_rules
,
357 icache_tree
*tree
= insn_table_cache_fields(instructions
);
359 lf_printf(file
, "#define WITH_IDECODE_CACHE_SIZE %d\n",
360 (code
& generate_with_icache
) ? icache_size
: 0);
361 lf_printf(file
, "\n");
363 /* create an instruction cache if being used */
364 if ((code
& generate_with_icache
)) {
366 lf_printf(file
, "typedef struct _idecode_cache {\n");
367 lf_printf(file
, " unsigned_word address;\n");
368 lf_printf(file
, " void *semantic;\n");
369 lf_printf(file
, " union {\n");
370 for (form
= tree
->children
;
374 lf_printf(file
, " struct {\n");
375 for (field
= form
->children
;
377 field
= field
->next
) {
378 cache_table
*cache_rule
;
380 for (cache_rule
= cache_rules
;
382 cache_rule
= cache_rule
->next
) {
383 if (strcmp(field
->name
, cache_rule
->old_name
) == 0) {
385 if (cache_rule
->new_name
!= NULL
)
386 lf_printf(file
, " %s %s; /* %s */\n",
387 (cache_rule
->type_def
== NULL
389 : cache_rule
->type_def
),
390 cache_rule
->new_name
,
391 cache_rule
->old_name
);
395 lf_printf(file
, " unsigned %s;\n", field
->name
);
397 lf_printf(file
, " } %s;\n", form
->name
);
399 lf_printf(file
, " } crack;\n");
400 lf_printf(file
, "} idecode_cache;\n");
403 /* alernativly, since no cache, #define the fields to be
404 extractions from the instruction variable. Emit a dummy
405 definition for idecode_cache to allow model_issue to not
406 be #ifdefed at the call level */
407 cache_table
*cache_rule
;
408 lf_printf(file
, "\n");
409 lf_printf(file
, "typedef void idecode_cache;\n");
410 lf_printf(file
, "\n");
411 for (cache_rule
= cache_rules
;
413 cache_rule
= cache_rule
->next
) {
414 if (cache_rule
->expression
!= NULL
415 && strlen(cache_rule
->expression
) > 0)
416 lf_printf(file
, "#define %s %s\n",
417 cache_rule
->new_name
, cache_rule
->expression
);
425 print_icache_function(lf
*file
,
427 insn_bits
*expanded_bits
,
428 opcode_field
*opcodes
,
429 cache_table
*cache_rules
)
433 /* generate code to enter decoded instruction into the icache */
434 lf_printf(file
, "\n");
435 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "EXTERN_ICACHE", "\n");
436 indent
= print_function_name(file
,
437 instruction
->file_entry
->fields
[insn_name
],
439 function_name_prefix_icache
);
440 lf_indent(file
, +indent
);
441 lf_printf(file
, "(%s)\n", ICACHE_FUNCTION_FORMAL
);
442 lf_indent(file
, -indent
);
444 /* function header */
445 lf_printf(file
, "{\n");
448 print_define_my_index(file
, instruction
->file_entry
);
449 print_itrace(file
, instruction
->file_entry
, 1/*putting-value-in-cache*/);
451 print_idecode_validate(file
, instruction
, opcodes
);
453 lf_printf(file
, "\n");
454 lf_printf(file
, "{\n");
456 print_icache_body(file
,
461 0/*get_value_from_cache*/,
462 1/*put_value_in_cache*/);
464 if ((code
& generate_with_semantic_icache
)) {
465 lf_printf(file
, "unsigned_word nia;\n");
466 lf_printf(file
, "cache_entry->address = cia;\n");
467 lf_printf(file
, "cache_entry->semantic = ");
468 print_function_name(file
,
469 instruction
->file_entry
->fields
[insn_name
],
471 function_name_prefix_semantics
);
472 lf_printf(file
, ";\n");
473 print_semantic_body(file
,
477 lf_printf(file
, "\n");
478 lf_printf(file
, "return nia;\n");
481 lf_printf(file
, "}\n");
483 if (!(code
& generate_with_semantic_icache
)) {
484 /* return the function propper (main sorts this one out) */
485 lf_printf(file
, "\n");
486 lf_printf(file
, "/* semantic routine */\n");
487 table_entry_print_cpp_line_nr(file
, instruction
->file_entry
);
488 lf_printf(file
, "return ");
489 print_function_name(file
,
490 instruction
->file_entry
->fields
[insn_name
],
492 function_name_prefix_semantics
);
493 lf_printf(file
, ";\n");
494 lf_print__internal_reference(file
);
498 lf_printf(file
, "}\n");
503 print_icache_definition(insn_table
*entry
,
509 cache_table
*cache_rules
= (cache_table
*)data
;
510 if (generate_expanded_instructions
) {
511 ASSERT(entry
->nr_insn
== 1
512 && entry
->opcode
== NULL
513 && entry
->parent
!= NULL
514 && entry
->parent
->opcode
!= NULL
);
515 ASSERT(entry
->nr_insn
== 1
516 && entry
->opcode
== NULL
517 && entry
->parent
!= NULL
518 && entry
->parent
->opcode
!= NULL
519 && entry
->parent
->opcode_rule
!= NULL
);
520 print_icache_function(file
,
522 entry
->expanded_bits
,
527 print_icache_function(file
,
538 print_icache_internal_function_declaration(insn_table
*table
,
541 table_entry
*function
)
543 ASSERT((code
& generate_with_icache
) != 0);
544 if (it_is("internal", function
->fields
[insn_flags
])) {
545 lf_printf(file
, "\n");
546 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "INLINE_ICACHE",
548 print_function_name(file
,
549 function
->fields
[insn_name
],
551 function_name_prefix_icache
);
552 lf_printf(file
, "\n(%s);\n", ICACHE_FUNCTION_FORMAL
);
558 print_icache_internal_function_definition(insn_table
*table
,
561 table_entry
*function
)
563 ASSERT((code
& generate_with_icache
) != 0);
564 if (it_is("internal", function
->fields
[insn_flags
])) {
565 lf_printf(file
, "\n");
566 lf_print_function_type(file
, ICACHE_FUNCTION_TYPE
, "INLINE_ICACHE",
568 print_function_name(file
,
569 function
->fields
[insn_name
],
571 function_name_prefix_icache
);
572 lf_printf(file
, "\n(%s)\n", ICACHE_FUNCTION_FORMAL
);
573 lf_printf(file
, "{\n");
575 lf_printf(file
, "/* semantic routine */\n");
576 table_entry_print_cpp_line_nr(file
, function
);
577 if ((code
& generate_with_semantic_icache
)) {
578 lf_print__c_code(file
, function
->annex
);
579 lf_printf(file
, "error(\"Internal function must longjump\\n\");\n");
580 lf_printf(file
, "return 0;\n");
583 lf_printf(file
, "return ");
584 print_function_name(file
,
585 function
->fields
[insn_name
],
587 function_name_prefix_semantics
);
588 lf_printf(file
, ";\n");
591 lf_print__internal_reference(file
);
593 lf_printf(file
, "}\n");