PowerPC64 ld segfault with code in non-executable sections
[external/binutils.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 }