gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / sim / ppc / gen-icache.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
4
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.
9
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.
14
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/>.
17
18 */
19
20
21 #include "misc.h"
22 #include "lf.h"
23 #include "table.h"
24
25 #include "filter.h"
26
27 #include "ld-decode.h"
28 #include "ld-cache.h"
29 #include "ld-insn.h"
30
31 #include "igen.h"
32
33 #include "gen-semantics.h"
34 #include "gen-idecode.h"
35 #include "gen-icache.h"
36
37
38
39 static void
40 print_icache_function_header(lf *file,
41 const char *basename,
42 insn_bits *expanded_bits,
43 int is_function_definition)
44 {
45 lf_printf(file, "\n");
46 lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", " ");
47 print_function_name(file,
48 basename,
49 expanded_bits,
50 function_name_prefix_icache);
51 lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
52 if (!is_function_definition)
53 lf_printf(file, ";");
54 lf_printf(file, "\n");
55 }
56
57
58 void
59 print_icache_declaration(insn_table *entry,
60 lf *file,
61 void *data,
62 insn *instruction,
63 int depth)
64 {
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],
69 entry->expanded_bits,
70 0/* is not function definition */);
71 }
72 else {
73 print_icache_function_header(file,
74 instruction->file_entry->fields[insn_name],
75 NULL,
76 0/* is not function definition */);
77 }
78 }
79
80
81
82 static void
83 print_icache_extraction(lf *file,
84 insn *instruction,
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,
90 int line_nr,
91 insn_field *cur_field,
92 insn_bits *bits,
93 icache_decl_type what_to_declare,
94 icache_body_type what_to_do,
95 const char *reason)
96 {
97 const char *expression;
98 ASSERT(entry_name != NULL);
99
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);
105 return;
106 }
107 else if (what_to_declare == define_variables) {
108 lf_indent_suppress(file);
109 lf_printf(file, "#define %s ", entry_name);
110 }
111 else {
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,
116 entry_name);
117 }
118
119 /* define a value for that storage area as determined by what is in
120 the cache */
121 if (bits != NULL
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));
138 else
139 lf_printf(file, "%d", bits->value);
140 }
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 */",
157 bits->value == 0,
158 original_name,
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))),
164 original_name,
165 (bits->value << (bits->field->last - bits->opcode->last)));
166 else
167 lf_printf(file, "%d /* %s == %d */",
168 (atol(entry_name + strlen(original_name) + strlen("_is_"))
169 == bits->value),
170 original_name,
171 bits->value);
172 }
173 else {
174 /* put the field in the local variable, possibly also enter it
175 into the cache */
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],
182 entry_name);
183 if (what_to_do & put_values_in_icache) /* also put it in the cache? */
184 lf_printf(file, " = ");
185 }
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);
194 else
195 lf_printf(file, "eval_%s", entry_name);
196 }
197 }
198
199 if (!((what_to_declare == define_variables)
200 || (what_to_declare == undef_variables)))
201 lf_printf(file, ";");
202 if (reason != NULL)
203 lf_printf(file, " /* %s - %s */", reason, expression);
204 lf_printf(file, "\n");
205 }
206
207
208 void
209 print_icache_body(lf *file,
210 insn *instruction,
211 insn_bits *expanded_bits,
212 cache_table *cache_rules,
213 icache_decl_type what_to_declare,
214 icache_body_type what_to_do)
215 {
216 insn_field *cur_field;
217
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");
224 break;
225 case declare_variables:
226 lf_printf(file, "declare");
227 break;
228 case undef_variables:
229 lf_printf(file, "#undef");
230 break;
231 }
232 lf_printf(file, " ");
233 switch (what_to_do) {
234 case get_values_from_icache:
235 lf_printf(file, "get-values-from-icache");
236 break;
237 case put_values_in_icache:
238 lf_printf(file, "put-values-in-icache");
239 break;
240 case both_values_and_icache:
241 lf_printf(file, "get-values-from-icache|put-values-in-icache");
242 break;
243 case do_not_use_icache:
244 lf_printf(file, "do-not-use-icache");
245 break;
246 }
247 lf_printf(file, " */\n");
248
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) {
253 insn_bits *bits;
254 int found_rule = 0;
255 /* find any corresponding value */
256 for (bits = expanded_bits;
257 bits != NULL;
258 bits = bits->last) {
259 if (bits->field == cur_field)
260 break;
261 }
262 /* try the cache rule table for what to do */
263 {
264 cache_table *cache_rule;
265 for (cache_rule = cache_rules;
266 cache_rule != NULL;
267 cache_rule = cache_rule->next) {
268 if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
269 found_rule = 1;
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,
274 instruction,
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,
281 cur_field,
282 bits,
283 what_to_declare,
284 do_not_use_icache,
285 "icache scratch");
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,
290 instruction,
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,
297 cur_field,
298 bits,
299 what_to_declare,
300 do_not_use_icache,
301 "semantic compute");
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,
306 instruction,
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,
313 cur_field,
314 bits,
315 ((what_to_do & put_values_in_icache)
316 ? declare_variables
317 : what_to_declare),
318 what_to_do,
319 "in icache");
320 }
321 }
322 }
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 */
326 if (found_rule == 0
327 && ((what_to_declare != undef_variables)
328 || !(what_to_do & put_values_in_icache)))
329 print_icache_extraction(file,
330 instruction,
331 cur_field->val_string,
332 NULL, NULL, NULL, /* type, exp, orig */
333 instruction->file_entry->file_name,
334 instruction->file_entry->line_nr,
335 cur_field,
336 bits,
337 ((what_to_do & put_values_in_icache)
338 ? declare_variables
339 : what_to_declare),
340 what_to_do,
341 "default in icache");
342 /* any thing else ... */
343 }
344 }
345
346 lf_print__internal_reference(file);
347
348 if ((code & generate_with_insn_in_icache)) {
349 lf_printf(file, "\n");
350 print_icache_extraction(file,
351 instruction,
352 "insn",
353 "instruction_word",
354 "instruction",
355 NULL, /* origin */
356 NULL, 0, /* file_name & line_nr */
357 NULL, NULL,
358 what_to_declare,
359 what_to_do,
360 NULL);
361 }
362 }
363
364
365
366 typedef struct _icache_tree icache_tree;
367 struct _icache_tree {
368 char *name;
369 icache_tree *next;
370 icache_tree *children;
371 };
372
373 static icache_tree *
374 icache_tree_insert(icache_tree *tree,
375 char *name)
376 {
377 icache_tree *new_tree;
378 /* find it */
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;
385 }
386 ASSERT(cur_tree == NULL
387 || strcmp(cur_tree->name, name) >= 0);
388 /* already in the tree */
389 if (cur_tree != NULL
390 && strcmp(cur_tree->name, name) == 0)
391 return cur_tree;
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;
399 return new_tree;
400 }
401
402
403 static icache_tree *
404 insn_table_cache_fields(insn_table *table)
405 {
406 icache_tree *tree = ZALLOC(icache_tree);
407 insn *instruction;
408 for (instruction = table->insns;
409 instruction != NULL;
410 instruction = instruction->next) {
411 insn_field *field;
412 icache_tree *form =
413 icache_tree_insert(tree,
414 instruction->file_entry->fields[insn_form]);
415 for (field = instruction->fields->first;
416 field != NULL;
417 field = field->next) {
418 if (field->is_string)
419 icache_tree_insert(form, field->val_string);
420 }
421 }
422 return tree;
423 }
424
425
426
427 extern void
428 print_icache_struct(insn_table *instructions,
429 cache_table *cache_rules,
430 lf *file)
431 {
432 icache_tree *tree = insn_table_cache_fields(instructions);
433
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");
438
439 /* create an instruction cache if being used */
440 if ((code & generate_with_icache)) {
441 icache_tree *form;
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;
447 form != NULL;
448 form = form->next) {
449 icache_tree *field;
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;
454 field != NULL;
455 field = field->next) {
456 cache_table *cache_rule;
457 int found_rule = 0;
458 for (cache_rule = cache_rules;
459 cache_rule != NULL;
460 cache_rule = cache_rule->next) {
461 if (strcmp(field->name, cache_rule->field_name) == 0) {
462 found_rule = 1;
463 if (cache_rule->derived_name != NULL)
464 lf_printf(file, " %s %s; /* %s */\n",
465 (cache_rule->type_def == NULL
466 ? "unsigned"
467 : cache_rule->type_def),
468 cache_rule->derived_name,
469 cache_rule->field_name);
470 }
471 }
472 if (!found_rule)
473 lf_printf(file, " unsigned %s;\n", field->name);
474 }
475 lf_printf(file, " } %s;\n", form->name);
476 }
477 lf_printf(file, " } crack;\n");
478 lf_printf(file, "} idecode_cache;\n");
479 }
480 else {
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");
484 }
485 lf_printf(file, "\n");
486 }
487
488
489
490 static void
491 print_icache_function(lf *file,
492 insn *instruction,
493 insn_bits *expanded_bits,
494 opcode_field *opcodes,
495 cache_table *cache_rules)
496 {
497 int indent;
498
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],
504 expanded_bits,
505 function_name_prefix_icache);
506 lf_indent(file, +indent);
507 lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL);
508 lf_indent(file, -indent);
509
510 /* function header */
511 lf_printf(file, "{\n");
512 lf_indent(file, +2);
513
514 print_my_defines(file, expanded_bits, instruction->file_entry);
515 print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
516
517 print_idecode_validate(file, instruction, opcodes);
518
519 lf_printf(file, "\n");
520 lf_printf(file, "{\n");
521 lf_indent(file, +2);
522 if ((code & generate_with_semantic_icache))
523 lf_printf(file, "unsigned_word nia;\n");
524 print_icache_body(file,
525 instruction,
526 expanded_bits,
527 cache_rules,
528 ((code & generate_with_direct_access)
529 ? define_variables
530 : declare_variables),
531 ((code & generate_with_semantic_icache)
532 ? both_values_and_icache
533 : put_values_in_icache));
534
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],
540 expanded_bits,
541 function_name_prefix_semantics);
542 lf_printf(file, ";\n");
543 lf_printf(file, "\n");
544
545 if ((code & generate_with_semantic_icache)) {
546 lf_printf(file, "/* semantic routine */\n");
547 print_semantic_body(file,
548 instruction,
549 expanded_bits,
550 opcodes);
551 lf_printf(file, "return nia;\n");
552 }
553
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],
559 expanded_bits,
560 function_name_prefix_semantics);
561 lf_printf(file, ";\n");
562 }
563
564 if ((code & generate_with_direct_access))
565 print_icache_body(file,
566 instruction,
567 expanded_bits,
568 cache_rules,
569 undef_variables,
570 ((code & generate_with_semantic_icache)
571 ? both_values_and_icache
572 : put_values_in_icache));
573
574 lf_indent(file, -2);
575 lf_printf(file, "}\n");
576 lf_indent(file, -2);
577 lf_printf(file, "}\n");
578 }
579
580
581 void
582 print_icache_definition(insn_table *entry,
583 lf *file,
584 void *data,
585 insn *instruction,
586 int depth)
587 {
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,
600 entry->insns,
601 entry->expanded_bits,
602 entry->opcode,
603 cache_rules);
604 }
605 else {
606 print_icache_function(file,
607 instruction,
608 NULL,
609 NULL,
610 cache_rules);
611 }
612 }
613
614
615
616 void
617 print_icache_internal_function_declaration(insn_table *table,
618 lf *file,
619 void *data,
620 table_entry *function)
621 {
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",
626 "\n");
627 print_function_name(file,
628 function->fields[insn_name],
629 NULL,
630 function_name_prefix_icache);
631 lf_printf(file, "\n(%s);\n", ICACHE_FUNCTION_FORMAL);
632 }
633 }
634
635
636 void
637 print_icache_internal_function_definition(insn_table *table,
638 lf *file,
639 void *data,
640 table_entry *function)
641 {
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",
646 "\n");
647 print_function_name(file,
648 function->fields[insn_name],
649 NULL,
650 function_name_prefix_icache);
651 lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL);
652 lf_printf(file, "{\n");
653 lf_indent(file, +2);
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");
660 }
661 else {
662 lf_printf(file, "return ");
663 print_function_name(file,
664 function->fields[insn_name],
665 NULL,
666 function_name_prefix_semantics);
667 lf_printf(file, ";\n");
668 }
669
670 lf_print__internal_reference(file);
671 lf_indent(file, -2);
672 lf_printf(file, "}\n");
673 }
674 }
This page took 0.044414 seconds and 4 git commands to generate.