[ARC] Fix ld testsuite failures.
[deliverable/binutils-gdb.git] / sim / ppc / gen-icache.c
index 7f5e5e182ae2f07b0bb173c3cb834d13a2d2f779..8acf3fba122e88cae5314b796fc3befd0924c20e 100644 (file)
@@ -1,10 +1,10 @@
 /*  This file is part of the program psim.
 
-    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+    Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
+    the Free Software Foundation; either version 3 of the License, or
     (at your option) any later version.
 
     This program is distributed in the hope that it will be useful,
@@ -13,8 +13,7 @@
     GNU General Public License for more details.
  
     You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+    along with this program; if not, see <http://www.gnu.org/licenses/>.
  
     */
 
@@ -83,45 +82,54 @@ print_icache_declaration(insn_table *entry,
 static void
 print_icache_extraction(lf *file,
                        insn *instruction,
-                       char *field_name,
-                       char *field_type,
-                       char *field_expression,
+                       const char *entry_name,
+                       const char *entry_type,
+                       const char *entry_expression,
+                       const char *original_name,
                        const char *file_name,
                        int line_nr,
                        insn_field *cur_field,
                        insn_bits *bits,
-                       int use_defines,
-                       int get_value_from_cache,
-                       int put_value_in_cache)
+                       icache_decl_type what_to_declare,
+                       icache_body_type what_to_do,
+                       const char *reason)
 {
-  ASSERT(field_name != NULL);
-  if (use_defines && put_value_in_cache) {
+  const char *expression;
+  ASSERT(entry_name != NULL);
+
+  /* Define a storage area for the cache element */
+  if (what_to_declare == undef_variables) {
     /* We've finished with the value - destory it */
     lf_indent_suppress(file);
-    lf_printf(file, "#undef %s\n", field_name);
+    lf_printf(file, "#undef %s\n", entry_name);
     return;
   }
-  else if (use_defines && get_value_from_cache) {
-      lf_indent_suppress(file);
-      lf_printf(file, "#define %s ", field_name);
+  else if (what_to_declare == define_variables) {
+    lf_indent_suppress(file);
+    lf_printf(file, "#define %s ", entry_name);
   }
   else {
-    lf_print__external_reference(file, line_nr, file_name);
-    lf_printf(file, "%s const %s __attribute__((__unused__)) = ",
-             field_type == NULL ? "unsigned" : field_type,
-             field_name);
+    if (file_name != NULL)
+      lf_print__external_reference(file, line_nr, file_name);
+    lf_printf(file, "%s const %s UNUSED = ",
+             entry_type == NULL ? "unsigned" : entry_type,
+             entry_name);
   }
 
+  /* define a value for that storage area as determined by what is in
+     the cache */
   if (bits != NULL
-      && ((bits->opcode->is_boolean
-          && bits->value == 0)
-         || !bits->opcode->is_boolean)
-      && strcmp(field_name, cur_field->val_string) == 0) {
-    /* The field has been made constant (as a result of expanding
-       instructions or similar) - define a constant variable with the
-       corresponding value. */
+      && strcmp(entry_name, cur_field->val_string) == 0
+      && ((bits->opcode->is_boolean && bits->value == 0)
+         || (!bits->opcode->is_boolean))) {
+    /* The simple field has been made constant (as a result of
+       expanding instructions or similar).  Remember that for a
+       boolean field, value is either 0 (implying the required
+       boolean_constant) or nonzero (implying some other value and
+       handled later below) - Define the variable accordingly */
+    expression = "constant field";
     ASSERT(bits->field == cur_field);
-    ASSERT(field_type == NULL);
+    ASSERT(entry_type == NULL);
     if (bits->opcode->is_boolean)
       lf_printf(file, "%d", bits->opcode->boolean_constant);
     else if (bits->opcode->last < bits->field->last)
@@ -130,33 +138,70 @@ print_icache_extraction(lf *file,
     else
       lf_printf(file, "%d", bits->value);
   }
+  else if (bits != NULL
+          && original_name != NULL
+          && strncmp(entry_name,
+                     original_name, strlen(original_name)) == 0
+          && strncmp(entry_name + strlen(original_name),
+                     "_is_", strlen("_is_")) == 0
+          && ((bits->opcode->is_boolean
+               && (atol(entry_name + strlen(original_name) + strlen("_is_"))
+                   == bits->opcode->boolean_constant))
+              || (!bits->opcode->is_boolean))) {
+    expression = "constant compare";
+    /* An entry, derived from ORIGINAL_NAME, is testing to see of the
+       ORIGINAL_NAME has a specific constant value.  That value
+       matching a boolean or constant field */
+    if (bits->opcode->is_boolean)
+      lf_printf(file, "%d /* %s == %d */",
+               bits->value == 0,
+               original_name,
+               bits->opcode->boolean_constant);
+    else if (bits->opcode->last < bits->field->last)
+      lf_printf(file, "%d /* %s == %d */",
+               (atol(entry_name + strlen(original_name) + strlen("_is_"))
+                == (bits->value << (bits->field->last - bits->opcode->last))),
+               original_name,
+               (bits->value << (bits->field->last - bits->opcode->last)));
+    else
+      lf_printf(file, "%d /* %s == %d */",
+               (atol(entry_name + strlen(original_name) + strlen("_is_"))
+                == bits->value),
+               original_name,
+               bits->value);
+  }
   else {
     /* put the field in the local variable, possibly also enter it
        into the cache */
-    /* getting it from the cache */
-    if (get_value_from_cache || put_value_in_cache) {
+    expression = "extraction";
+    /* handle the cache */
+    if ((what_to_do & get_values_from_icache)
+       || (what_to_do & put_values_in_icache)) {
       lf_printf(file, "cache_entry->crack.%s.%s",
                instruction->file_entry->fields[insn_form],
-               field_name);
-      if (put_value_in_cache) /* also put it in the cache? */
+               entry_name);
+      if (what_to_do & put_values_in_icache) /* also put it in the cache? */
        lf_printf(file, " = ");
     }
-    if (!get_value_from_cache) {
-      if (strcmp(field_name, cur_field->val_string) == 0)
+    if ((what_to_do & put_values_in_icache)
+       || what_to_do == do_not_use_icache) {
+      if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0)
        lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
                  i2target(hi_bit_nr, cur_field->first),
                  i2target(hi_bit_nr, cur_field->last));
-      else if (field_expression != NULL)
-       lf_printf(file, "%s", field_expression);
+      else if (entry_expression != NULL)
+       lf_printf(file, "%s", entry_expression);
       else
-       lf_printf(file, "eval_%s", field_name);
+       lf_printf(file, "eval_%s", entry_name);
     }
   }
 
-  if (use_defines && get_value_from_cache)
-    lf_printf(file, "\n");
-  else
-    lf_printf(file, ";\n");
+  if (!((what_to_declare == define_variables)
+       || (what_to_declare == undef_variables)))
+    lf_printf(file, ";");
+  if (reason != NULL)
+    lf_printf(file, " /* %s - %s */", reason, expression);
+  lf_printf(file, "\n");
 }
 
 
@@ -165,16 +210,41 @@ print_icache_body(lf *file,
                  insn *instruction,
                  insn_bits *expanded_bits,
                  cache_table *cache_rules,
-                 int use_defines,
-                 int get_value_from_cache,
-                 int put_value_in_cache)
+                 icache_decl_type what_to_declare,
+                 icache_body_type what_to_do)
 {
   insn_field *cur_field;
   
   /* extract instruction fields */
-  lf_printf(file, "/* extraction: %s defines=%d get-value=%d put-value=%d */\n",
-           instruction->file_entry->fields[insn_format],
-           use_defines, get_value_from_cache, put_value_in_cache);
+  lf_printf(file, "/* extraction: %s ",
+           instruction->file_entry->fields[insn_format]);
+  switch (what_to_declare) {
+  case define_variables:
+    lf_printf(file, "#define");
+    break;
+  case declare_variables:
+    lf_printf(file, "declare");
+    break;
+  case undef_variables:
+    lf_printf(file, "#undef");
+    break;
+  }
+  lf_printf(file, " ");
+  switch (what_to_do) {
+  case get_values_from_icache:
+    lf_printf(file, "get-values-from-icache");
+    break;
+  case put_values_in_icache:
+    lf_printf(file, "put-values-in-icache");
+    break;
+  case both_values_and_icache:
+    lf_printf(file, "get-values-from-icache|put-values-in-icache");
+    break;
+  case do_not_use_icache:
+    lf_printf(file, "do-not-use-icache");
+    break;
+  }
+  lf_printf(file, " */\n");
   
   for (cur_field = instruction->fields->first;
        cur_field->first < insn_bit_size;
@@ -190,100 +260,105 @@ print_icache_body(lf *file,
          break;
       }
       /* try the cache rule table for what to do */
-      if (get_value_from_cache || put_value_in_cache) {      
+      {
        cache_table *cache_rule;
        for (cache_rule = cache_rules;
             cache_rule != NULL;
             cache_rule = cache_rule->next) {
-         if (strcmp(cur_field->val_string, cache_rule->old_name) == 0) {
+         if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
            found_rule = 1;
-           if (cache_rule->type == compute_value
-               && put_value_in_cache
-               && !use_defines)
+           if (cache_rule->type == scratch_value
+               && ((what_to_do & put_values_in_icache)
+                   || what_to_do == do_not_use_icache))
+             print_icache_extraction(file,
+                                     instruction,
+                                     cache_rule->derived_name,
+                                     cache_rule->type_def,
+                                     cache_rule->expression,
+                                     cache_rule->field_name,
+                                     cache_rule->file_entry->file_name,
+                                     cache_rule->file_entry->line_nr,
+                                     cur_field,
+                                     bits,
+                                     what_to_declare,
+                                     do_not_use_icache,
+                                     "icache scratch");
+           else if (cache_rule->type == compute_value
+                    && ((what_to_do & get_values_from_icache)
+                        || what_to_do == do_not_use_icache))
              print_icache_extraction(file,
                                      instruction,
-                                     cache_rule->new_name,
+                                     cache_rule->derived_name,
                                      cache_rule->type_def,
                                      cache_rule->expression,
+                                     cache_rule->field_name,
                                      cache_rule->file_entry->file_name,
                                      cache_rule->file_entry->line_nr,
                                      cur_field,
                                      bits,
-                                     0 /*use_defines*/,
-                                     0 /*get-value-from-cache*/,
-                                     0 /*put-value-in-cache*/);
-           else if (cache_rule->type == cache_value)
+                                     what_to_declare,
+                                     do_not_use_icache,
+                                     "semantic compute");
+           else if (cache_rule->type == cache_value
+                    && ((what_to_declare != undef_variables)
+                        || !(what_to_do & put_values_in_icache)))
              print_icache_extraction(file,
                                      instruction,
-                                     cache_rule->new_name,
+                                     cache_rule->derived_name,
                                      cache_rule->type_def,
                                      cache_rule->expression,
+                                     cache_rule->field_name,
                                      cache_rule->file_entry->file_name,
                                      cache_rule->file_entry->line_nr,
                                      cur_field,
                                      bits,
-                                     use_defines,
-                                     get_value_from_cache,
-                                     put_value_in_cache);
+                                     ((what_to_do & put_values_in_icache)
+                                      ? declare_variables
+                                      : what_to_declare),
+                                     what_to_do,
+                                     "in icache");
          }
        }
       }
-      if (found_rule == 0)
+      /* No rule at all, assume that this is needed in the semantic
+         function (when values are extracted from the icache) and
+         hence must be put into the cache */
+      if (found_rule == 0
+         && ((what_to_declare != undef_variables)
+             || !(what_to_do & put_values_in_icache)))
        print_icache_extraction(file,
                                instruction,
                                cur_field->val_string,
-                               0,
-                               0,
+                               NULL, NULL, NULL, /* type, exp, orig */
                                instruction->file_entry->file_name,
                                instruction->file_entry->line_nr,
                                cur_field,
                                bits,
-                               use_defines,
-                               get_value_from_cache,
-                               put_value_in_cache);
-      /* if any (XXX == 0), output a corresponding test */
-      if (instruction->file_entry->annex != NULL) {
-       char *field_name = cur_field->val_string;
-       char *is_0_ptr = instruction->file_entry->annex;
-       int field_len = strlen(field_name);
-       if (strlen(is_0_ptr) >= (strlen("_is_0") + field_len)) {
-         is_0_ptr += field_len;
-         while ((is_0_ptr = strstr(is_0_ptr, "_is_0")) != NULL) {
-           if (strncmp(is_0_ptr - field_len, field_name, field_len) == 0
-               && !isalpha(is_0_ptr[ - field_len - 1])) {
-             if (!use_defines || (use_defines && get_value_from_cache)) {
-               if (use_defines) {
-                 lf_indent_suppress(file);
-                 lf_printf(file, "#define %s_is_0 ", field_name);
-               }
-               else {
-                 table_entry_print_cpp_line_nr(file, instruction->file_entry);
-                 lf_printf(file, "const unsigned %s_is_0 __attribute__((__unused__)) = ",
-                           field_name);
-               }
-               if (bits != NULL)
-                 lf_printf(file, "(%d == 0)", bits->value);
-               else
-                 lf_printf(file, "(%s == 0)", field_name);
-               if (use_defines)
-                 lf_printf(file, "\n");
-               else
-                 lf_printf(file, ";\n");
-             }
-             else if (use_defines && put_value_in_cache) {
-               lf_indent_suppress(file);
-               lf_printf(file, "#undef %s_is_0\n", field_name);
-             }
-             break;
-           }
-           is_0_ptr += strlen("_is_0");
-         }
-       }
-      }
+                               ((what_to_do & put_values_in_icache)
+                                ? declare_variables
+                                : what_to_declare),
+                               what_to_do,
+                               "default in icache");
       /* any thing else ... */
     }
   }
+
   lf_print__internal_reference(file);
+
+  if ((code & generate_with_insn_in_icache)) {
+    lf_printf(file, "\n");
+    print_icache_extraction(file,
+                           instruction,
+                           "insn",
+                           "instruction_word",
+                           "instruction",
+                           NULL, /* origin */
+                           NULL, 0, /* file_name & line_nr */
+                           NULL, NULL,
+                           what_to_declare,
+                           what_to_do,
+                           NULL);
+  }
 }
 
 
@@ -356,6 +431,7 @@ print_icache_struct(insn_table *instructions,
 {
   icache_tree *tree = insn_table_cache_fields(instructions);
   
+  lf_printf(file, "\n");
   lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
            (code & generate_with_icache) ? icache_size : 0);
   lf_printf(file, "\n");
@@ -372,6 +448,8 @@ print_icache_struct(insn_table *instructions,
         form = form->next) {
       icache_tree *field;
       lf_printf(file, "    struct {\n");
+      if (code & generate_with_insn_in_icache)
+       lf_printf(file, "      instruction_word insn;\n");
       for (field = form->children;
           field != NULL;
           field = field->next) {
@@ -380,15 +458,15 @@ print_icache_struct(insn_table *instructions,
        for (cache_rule = cache_rules;
             cache_rule != NULL;
             cache_rule = cache_rule->next) {
-         if (strcmp(field->name, cache_rule->old_name) == 0) {
+         if (strcmp(field->name, cache_rule->field_name) == 0) {
            found_rule = 1;
-           if (cache_rule->new_name != NULL)
+           if (cache_rule->derived_name != NULL)
              lf_printf(file, "      %s %s; /* %s */\n",
                        (cache_rule->type_def == NULL
                         ? "unsigned" 
                         : cache_rule->type_def),
-                       cache_rule->new_name,
-                       cache_rule->old_name);
+                       cache_rule->derived_name,
+                       cache_rule->field_name);
          }
        }
        if (!found_rule)
@@ -400,23 +478,11 @@ print_icache_struct(insn_table *instructions,
     lf_printf(file, "} idecode_cache;\n");
   }
   else {
-    /* alernativly, since no cache, #define the fields to be
-       extractions from the instruction variable.  Emit a dummy
-       definition for idecode_cache to allow model_issue to not
-       be #ifdefed at the call level */
-    cache_table *cache_rule;
-    lf_printf(file, "\n");
+    /* alernativly, since no cache, emit a dummy definition for
+       idecode_cache so that code refering to the type can still compile */
     lf_printf(file, "typedef void idecode_cache;\n");
-    lf_printf(file, "\n");
-    for (cache_rule = cache_rules;
-        cache_rule != NULL;
-        cache_rule = cache_rule->next) {
-      if (cache_rule->expression != NULL
-         && strlen(cache_rule->expression) > 0)
-       lf_printf(file, "#define %s %s\n",
-                 cache_rule->new_name, cache_rule->expression);
-    }
   }
+  lf_printf(file, "\n");
 }
 
 
@@ -445,7 +511,7 @@ print_icache_function(lf *file,
   lf_printf(file, "{\n");
   lf_indent(file, +2);
   
-  print_define_my_index(file, instruction->file_entry);
+  print_my_defines(file, expanded_bits, instruction->file_entry);
   print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
   
   print_idecode_validate(file, instruction, opcodes);
@@ -453,47 +519,60 @@ print_icache_function(lf *file,
   lf_printf(file, "\n");
   lf_printf(file, "{\n");
   lf_indent(file, +2);
+  if ((code & generate_with_semantic_icache))
+    lf_printf(file, "unsigned_word nia;\n");
   print_icache_body(file,
                    instruction,
                    expanded_bits,
                    cache_rules,
-                   0/*use_defines*/,
-                   0/*get_value_from_cache*/,
-                   1/*put_value_in_cache*/);
+                   ((code & generate_with_direct_access)
+                    ? define_variables
+                    : declare_variables),
+                   ((code & generate_with_semantic_icache)
+                    ? both_values_and_icache
+                    : put_values_in_icache));
   
+  lf_printf(file, "\n");
+  lf_printf(file, "cache_entry->address = cia;\n");
+  lf_printf(file, "cache_entry->semantic = ");
+  print_function_name(file,
+                     instruction->file_entry->fields[insn_name],
+                     expanded_bits,
+                     function_name_prefix_semantics);
+  lf_printf(file, ";\n");
+  lf_printf(file, "\n");
+
   if ((code & generate_with_semantic_icache)) {
-    lf_printf(file, "unsigned_word nia;\n");
-    lf_printf(file, "cache_entry->address = cia;\n");
-    lf_printf(file, "cache_entry->semantic = ");
-    print_function_name(file,
-                       instruction->file_entry->fields[insn_name],
-                       expanded_bits,
-                       function_name_prefix_semantics);
-    lf_printf(file, ";\n");
+    lf_printf(file, "/* semantic routine */\n");
     print_semantic_body(file,
                        instruction,
                        expanded_bits,
                        opcodes);
-    lf_printf(file, "\n");
     lf_printf(file, "return nia;\n");
   }
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
   
   if (!(code & generate_with_semantic_icache)) {
-    /* return the function propper (main sorts this one out) */
-    lf_printf(file, "\n");
-    lf_printf(file, "/* semantic routine */\n");
-    table_entry_print_cpp_line_nr(file, instruction->file_entry);
+    lf_printf(file, "/* return the function proper */\n");
     lf_printf(file, "return ");
     print_function_name(file,
                        instruction->file_entry->fields[insn_name],
                        expanded_bits,
                        function_name_prefix_semantics);
     lf_printf(file, ";\n");
-    lf_print__internal_reference(file);
   }
   
+  if ((code & generate_with_direct_access))
+    print_icache_body(file,
+                     instruction,
+                     expanded_bits,
+                     cache_rules,
+                     undef_variables,
+                     ((code & generate_with_semantic_icache)
+                      ? both_values_and_icache
+                      : put_values_in_icache));
+
+  lf_indent(file, -2);
+  lf_printf(file, "}\n");
   lf_indent(file, -2);
   lf_printf(file, "}\n");
 }
@@ -543,7 +622,7 @@ print_icache_internal_function_declaration(insn_table *table,
   ASSERT((code & generate_with_icache) != 0);
   if (it_is("internal", function->fields[insn_flags])) {
     lf_printf(file, "\n");
-    lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
+    lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "PSIM_INLINE_ICACHE",
                           "\n");
     print_function_name(file,
                        function->fields[insn_name],
@@ -563,7 +642,7 @@ print_icache_internal_function_definition(insn_table *table,
   ASSERT((code & generate_with_icache) != 0);
   if (it_is("internal", function->fields[insn_flags])) {
     lf_printf(file, "\n");
-    lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
+    lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "PSIM_INLINE_ICACHE",
                           "\n");
     print_function_name(file,
                        function->fields[insn_name],
This page took 0.03497 seconds and 4 git commands to generate.