Speedups from Andrew
authorMichael Meissner <gnu@the-meissners.org>
Mon, 16 Oct 1995 20:17:35 +0000 (20:17 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Mon, 16 Oct 1995 20:17:35 +0000 (20:17 +0000)
sim/ppc/ChangeLog
sim/ppc/gen.c

index 543f82fd4b4dce19635852185b73baa6d05bf8d1..2ad375d49cd1c3b48b3a3f11efc6007583ef1803 100644 (file)
@@ -1,5 +1,14 @@
+Wed Oct 11 17:13:15 1995  Andrew Cagney  <cagney@highland.com.au>
+
+       * gen.c, ppc-instructions, psim.c: Fix code for generating
+       cracking instruction cache.  Delete the code that cached just the
+       result from doing an instruction lookup - this ran slower than no
+       cache at all.
+
 Fri Oct 13 09:58:43 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
 
+       * Makefile.in (gen.o): Include $(INLINE_CFLAGS).
+
        * debug.h (ppc_trace): Rename from trace, to avoid a conflict with
        TCL when gdb is linked with the simulator.
        * debug.c (ppc_trace): Ditto.
index b9870ab65d7b74debba654510b5385eb1b758ef5..ced6e418cf45eff03646668e80c6d3cac380d82c 100644 (file)
@@ -1232,7 +1232,8 @@ insn_table_load_insns(char *file_name)
   table->opcode_rule = opcode_table;
 
   while ((file_entry = file_table_read(file)) != NULL) {
-    if (it_is("function", file_entry->fields[insn_flags])) {
+    if (it_is("function", file_entry->fields[insn_flags])
+       || it_is("internal", file_entry->fields[insn_flags])) {
       insn_table_insert_function(table, file_entry);
     }
     else {
@@ -1575,20 +1576,6 @@ lf_print_idecode_table(lf *file,
        lf_printf(file, "           table_entry->function_or_table)\n");
        lf_printf(file, "          (%s));\n", insn_actual);
       }
-      else if (idecode_cache == 1 && can_assume_leaf) {
-       lf_printf(file, "ASSERT(!entry->shift);\n");
-       lf_printf(file, "return ((idecode_semantic*)\n");
-       lf_printf(file, "        table_entry->function_or_table);\n");
-      }
-      else if (idecode_cache == 1 && !can_assume_leaf) {
-       lf_printf(file, "if (table_entry->shift == 0)\n");
-       lf_printf(file, "  return ((idecode_semantic*)\n");
-       lf_printf(file, "          table_entry->function_or_table);\n");
-       lf_printf(file, "else if (table_entry->shift == -1)\n");
-       lf_printf(file, "  return (((idecode_crack*)\n");
-       lf_printf(file, "           table_entry->function_or_table)\n");
-       lf_printf(file, "          (%s));\n", insn_actual);
-      }
       else {
        lf_printf(file, "if (table_entry->shift == 0)\n");
        lf_printf(file, "  return (((idecode_crack*)\n");
@@ -1823,7 +1810,7 @@ semantics_h_print_function(lf *file,
                         expanded_bits,
                         function_name_prefix_semantics);
   lf_printf(file, "\n(%s);\n",
-           idecode_cache > 1 ? cache_insn_formal : insn_formal);
+           (idecode_cache ? cache_insn_formal : insn_formal));
 }
 
 
@@ -1999,48 +1986,43 @@ gen_icache_h(icache_tree *tree,
 
   /* create an instruction cache if being used */
   if (idecode_cache) {
+    icache_tree *form;
     lf_printf(file, "typedef struct _idecode_cache {\n");
     lf_printf(file, "  unsigned_word address;\n");
     lf_printf(file, "  void *semantic;\n");
-    if (idecode_cache == 1) {
-      lf_printf(file, "  instruction_word instruction;\n");
-    }
-    else {
-      icache_tree *form;
-      lf_printf(file, "  union {\n");
-      for (form = tree->children;
-          form != NULL;
-          form = form->next) {
-       icache_tree *field;
-       lf_printf(file, "    struct {\n");
-       for (field = form->children;
-            field != NULL;
-            field = field->next) {
-         extraction_rules *rule;
-         int found_rule = 0;
-         for (rule = cachable_values;
-              rule->valid;
-              rule++) {
-           if (strcmp(field->name, rule->old_name) == 0) {
-             found_rule = 1;
-             if (rule->new_name != NULL)
-               lf_printf(file, "      %s %s; /* %s */\n",
-                         rule->type == NULL ? "unsigned" : rule->type,
-                         rule->new_name, rule->old_name);
-           }
+    lf_printf(file, "  union {\n");
+    for (form = tree->children;
+        form != NULL;
+        form = form->next) {
+      icache_tree *field;
+      lf_printf(file, "    struct {\n");
+      for (field = form->children;
+          field != NULL;
+          field = field->next) {
+       extraction_rules *rule;
+       int found_rule = 0;
+       for (rule = cachable_values;
+            rule->valid;
+            rule++) {
+         if (strcmp(field->name, rule->old_name) == 0) {
+           found_rule = 1;
+           if (rule->new_name != NULL)
+             lf_printf(file, "      %s %s; /* %s */\n",
+                       rule->type == NULL ? "unsigned" : rule->type,
+                       rule->new_name, rule->old_name);
          }
-         if (!found_rule)
-           lf_printf(file, "      unsigned %s;\n", field->name);
        }
-       lf_printf(file, "    } %s;\n", form->name);
+       if (!found_rule)
+         lf_printf(file, "      unsigned %s;\n", field->name);
       }
-      lf_printf(file, "  } crack;\n");
+      lf_printf(file, "    } %s;\n", form->name);
     }
+    lf_printf(file, "  } crack;\n");
     lf_printf(file, "} idecode_cache;\n");
   }
-
-  /* define various fields according to the cache */
-  if (idecode_cache <= 1) {
+  else {
+    /* alernativly, since no cache, #define the fields to be
+       extractions from the instruction variable */
     extraction_rules *rule;
     lf_printf(file, "\n");
     for (rule = cachable_values;
@@ -2216,65 +2198,120 @@ lf_print_c_extractions(lf *file,
 static void
 lf_print_idecode_illegal(lf *file)
 {
-  switch (idecode_cache) {
-  case 0:
-    lf_printf(file, "return semantic_illegal(%s);\n", insn_actual);
-    break;
-  case 1:
-    lf_printf(file, "return semantic_illegal;\n");
-    break;
-  default:
+  if (idecode_cache)
     lf_printf(file, "return idecode_illegal(%s);\n", cache_idecode_actual);
-  }
+  else
+    lf_printf(file, "return semantic_illegal(%s);\n", insn_actual);
 }
 
 
+static void
+lf_print_idecode_floating_point_unavailable(lf *file)
+{
+  if (idecode_cache)
+    lf_printf(file, "return idecode_floating_point_unavailable(%s);\n",
+             cache_idecode_actual);
+  else
+    lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
+             insn_actual);
+}
+
+
+/* Output code to do any final checks on the decoded instruction.
+   This includes things like verifying any on decoded fields have the
+   correct value and checking that (for floating point) floating point
+   hardware isn't disabled */
+
 static void
 lf_print_c_validate(lf *file,
                    insn *instruction,
                    opcode_field *opcodes)
 {
-  unsigned check_mask = 0;
-  unsigned check_val = 0;
-  insn_field *field;
-  opcode_field *opcode;
+  /* Validate: unchecked instruction fields
 
-  for (field = instruction->fields->first;
-       field->first < insn_size;
-       field = field->next) {
+     If any constant fields in the instruction were not checked by the
+     idecode tables, output code to check that they have the correct
+     value here */
+  { 
+    unsigned check_mask = 0;
+    unsigned check_val = 0;
+    insn_field *field;
+    opcode_field *opcode;
+
+    /* form check_mask/check_val containing what needs to be checked
+       in the instruction */
+    for (field = instruction->fields->first;
+        field->first < insn_size;
+        field = field->next) {
 
-    check_mask <<= field->width;
-    check_val <<= field->width;
+      check_mask <<= field->width;
+      check_val <<= field->width;
 
-    /* is it a constant that could need validating? */
-    if (!field->is_int && !field->is_slash)
-      continue;
+      /* is it a constant that could need validating? */
+      if (!field->is_int && !field->is_slash)
+       continue;
 
-    /* has it been checked by a table? */
-    for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
-      if (field->first >= opcode->first
-         && field->last <= opcode->last)
-       break;
+      /* has it been checked by a table? */
+      for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
+       if (field->first >= opcode->first
+           && field->last <= opcode->last)
+         break;
+      }
+      if (opcode != NULL)
+       continue;
+
+      check_mask |= (1 << field->width)-1;
+      check_val |= field->val_int;
     }
-    if (opcode != NULL)
-      continue;
 
-    check_mask |= (1 << field->width)-1;
-    check_val |= field->val_int;
+    /* if any bits not checked by opcode tables, output code to check them */
+    if (check_mask) {
+      lf_printf(file, "\n");
+      lf_printf(file, "/* validate: %s */\n",
+               instruction->file_entry->fields[insn_format]);
+      lf_printf(file, "if ((instruction & 0x%x) != 0x%x)\n",
+               check_mask, check_val);
+      lf_indent(file, +2);
+      lf_print_idecode_illegal(file);
+      lf_indent(file, -2);
+    }
   }
 
-  /* if any bits not checked by opcode tables, output code to check them */
-  if (check_mask) {
-    lf_printf(file, "\n");
-    lf_printf(file, "/* validate: %s */\n",
-             instruction->file_entry->fields[insn_format]);
-    lf_printf(file, "if ((instruction & 0x%x) != 0x%x)\n",
-             check_mask, check_val);
-    lf_indent(file, +2);
-    lf_print_idecode_illegal(file);
-    lf_indent(file, -2);
+  /* Validate floating point hardware
+
+     If the simulator is being built with out floating point hardware
+     (different to it being disabled in the MSR) then floating point
+     instructions are invalid */
+  {
+    if (it_is("f", instruction->file_entry->fields[insn_flags])) {
+      lf_printf(file, "\n");
+      lf_printf(file, "/* Validate: FP hardware exists */\n");
+      lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
+      lf_indent(file, +2);
+      lf_print_idecode_illegal(file);
+      lf_indent(file, -2);
+    }
   }
 
+  /* Validate: Floating Point available
+
+     If floating point is not available, we enter a floating point
+     unavailable interrupt into the cache instead of the instruction
+     proper.
+
+     The PowerPC spec requires a CSI after MSR[FP] is changed and when
+     ever a CSI occures we flush the instruction cache. */
+
+  {
+    if (it_is("f", instruction->file_entry->fields[insn_flags])) {
+      lf_printf(file, "\n");
+      lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
+      lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
+      lf_indent(file, +2);
+      lf_print_idecode_floating_point_unavailable(file);
+      lf_indent(file, -2);
+    }
+  }
 }
 
 
@@ -2343,32 +2380,15 @@ lf_print_c_semantic(lf *file,
   lf_print_c_extractions(file,
                         instruction,
                         expanded_bits,
-                        idecode_cache > 1/*get_value_from_cache*/,
+                        idecode_cache/*get_value_from_cache*/,
                         0/*put_value_in_cache*/);
 
   lf_print_ptrace(file);
 
-  /* generate code to check previously unchecked fields */
-  if (idecode_cache < 2)
+  /* validate the instruction, if a cache this has already been done */
+  if (!idecode_cache)
     lf_print_c_validate(file, instruction, opcodes);
 
-  /* if floating-point generate checks that a. floating point hardware
-     exists and b. floating point is enabled */
-  if (it_is("f", instruction->file_entry->fields[insn_flags])) {
-    lf_printf(file, "\n");
-    lf_printf(file, "/* verify: FP hardware exists */\n");
-    lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
-    lf_indent(file, +2);
-    lf_print_idecode_illegal(file);
-    lf_indent(file, -2);
-    lf_printf(file, "\n");
-    lf_printf(file, "/* verify: FP is enabled */\n");
-    lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
-    lf_indent(file, +2);
-    lf_printf(file, "floating_point_unavailable_interrupt(processor, cia);\n");
-    lf_indent(file, -2);
-  }
-
   /* generate the code (or at least something */
   if (instruction->file_entry->annex != NULL) {
     /* true code */
@@ -2418,7 +2438,7 @@ lf_print_c_semantic_function_header(lf *file,
                         expanded_bits,
                         function_name_prefix_semantics);
   lf_printf(file, "\n(%s)\n",
-           idecode_cache > 1 ? cache_insn_formal : insn_formal);
+           (idecode_cache ? cache_insn_formal : insn_formal));
 }
 
 static void
@@ -2558,14 +2578,14 @@ gen_idecode_h(insn_table *table, lf *file)
   lf_printf(file, "#include \"icache.h\"\n");
   lf_printf(file, "\n");
   lf_printf(file, "typedef unsigned_word idecode_semantic\n(%s);\n",
-           idecode_cache < 2 ? insn_formal : cache_insn_formal);
+           (idecode_cache ? cache_insn_formal : insn_formal));
   lf_printf(file, "\n");
-  if (!idecode_cache)
+  if (idecode_cache)
+    lf_printf(file, "INLINE_IDECODE idecode_semantic *idecode\n(%s);\n",
+             cache_idecode_formal);
+  else
     lf_printf(file, "INLINE_IDECODE unsigned_word idecode_issue\n(%s);\n",
              insn_formal);
-  else if (idecode_cache)
-    lf_printf(file, "INLINE_IDECODE idecode_semantic *idecode\n(%s);\n",
-             idecode_cache == 1 ? insn_formal : cache_idecode_formal);
   lf_printf(file, "\n");
   lf_printf(file, "#endif /* _IDECODE_H_ */\n");
 }
@@ -2607,9 +2627,9 @@ idecode_table_leaf(insn_table *entry,
       lf_print_function_name(file,
                             entry->insns->file_entry->fields[insn_name],
                             entry->expanded_bits,
-                            (idecode_cache < 2
-                             ? function_name_prefix_semantics
-                             : function_name_prefix_idecode));
+                            (idecode_cache
+                             ? function_name_prefix_idecode
+                             : function_name_prefix_semantics));
       lf_printf(file, " },\n");
     }
     else if (entry->opcode_rule->use_switch) {
@@ -2659,7 +2679,7 @@ idecode_table_padding(insn_table *table,
 
   if (!table->opcode_rule->use_switch) {
     lf_printf(file, "  /*%d*/ { 0, 0, %s_illegal },\n",
-             opcode_nr, idecode_cache > 1 ? "idecode" : "semantic");
+             opcode_nr, (idecode_cache ? "idecode" : "semantic"));
   }
 }
 
@@ -2705,15 +2725,13 @@ idecode_switch_leaf(insn_table *entry,
       lf_print_function_name(file,
                             entry->insns->file_entry->fields[insn_name],
                             entry->expanded_bits,
-                            (idecode_cache < 2
-                             ? function_name_prefix_semantics
-                             : function_name_prefix_idecode));
-      if (!idecode_cache)
-       lf_printf(file, "(%s);\n", insn_actual);
-      else if (idecode_cache == 1)
-       lf_printf(file, ";\n");
-      else
+                            (idecode_cache
+                             ? function_name_prefix_idecode
+                             : function_name_prefix_semantics));
+      if (idecode_cache)
        lf_printf(file, "(%s);\n", cache_idecode_actual);
+      else
+       lf_printf(file, "(%s);\n", insn_actual);
     }
     else if (entry->opcode_rule->use_switch) {
       /* switch calling switch */
@@ -2801,7 +2819,7 @@ idecode_expand_if_switch(insn_table *table,
     lf_printf(file, "STATIC_INLINE_IDECODE void\n");
     lf_print_table_name(file, table);
     lf_printf(file, "\n(%s)\n",
-             idecode_cache ? cache_idecode_formal : insn_formal);
+             (idecode_cache ? cache_idecode_formal : insn_formal));
     lf_printf(file, "{\n");
     {
       lf_indent(file, +2);
@@ -2862,6 +2880,39 @@ idecode_crack_insn(insn_table *entry,
                              NULL);
 }
 
+static void
+idecode_c_internal_function(insn_table *table,
+                           void *data,
+                           file_table_entry *function)
+{
+  lf *file = (lf*)data;
+  ASSERT(idecode_cache != 0);
+  if (it_is("internal", function->fields[insn_flags])) {
+    lf_printf(file, "\n");
+    lf_printf(file, "STATIC_INLINE_IDECODE idecode_semantic *\n");
+    lf_print_function_name(file,
+                          function->fields[insn_name],
+                          NULL,
+                          function_name_prefix_idecode);
+    lf_printf(file, "\n(%s)\n", cache_idecode_formal);
+    lf_printf(file, "{\n");
+    lf_indent(file, +2);
+    lf_printf(file, "/* semantic routine */\n");
+    lf_print_c_line_nr(file, function);
+    lf_printf(file, "return ");
+    lf_print_function_name(file,
+                          function->fields[insn_name],
+                          NULL,
+                          function_name_prefix_semantics);
+    lf_printf(file, ";\n");
+
+    lf_print_file_line_nr(file);
+    lf_indent(file, -2);
+    lf_printf(file, "}\n");
+  }
+}
+
+
 /****************************************************************/
 
 static void
@@ -2886,7 +2937,7 @@ gen_idecode_c(insn_table *table, lf *file)
   lf_printf(file, "\n");
   lf_printf(file, "\n");
   lf_printf(file, "typedef idecode_semantic *idecode_crack\n(%s);\n",
-           idecode_cache > 1 ? cache_idecode_formal : insn_formal);
+           (idecode_cache ? cache_idecode_formal : insn_formal));
   lf_printf(file, "\n");
   lf_printf(file, "typedef struct _idecode_table_entry {\n");
   lf_printf(file, "  unsigned shift;\n");
@@ -2896,8 +2947,16 @@ gen_idecode_c(insn_table *table, lf *file)
   lf_printf(file, "\n");
   lf_printf(file, "\n");
 
+  /* output `internal' invalid/floating-point unavailable functions
+     where needed */
+  if (idecode_cache) {
+    insn_table_traverse_function(table,
+                                file,
+                                idecode_c_internal_function);
+  }
+
   /* output cracking functions where needed */
-  if (idecode_cache > 1) {
+  if (idecode_cache) {
     if (idecode_expand_semantics)
       insn_table_traverse_tree(table,
                               file,
@@ -2935,12 +2994,12 @@ gen_idecode_c(insn_table *table, lf *file)
 
   /* output the main idecode routine */
   lf_printf(file, "\n");
-  if (!idecode_cache)
+  if (idecode_cache)
+    lf_printf(file, "INLINE_IDECODE idecode_semantic *\nidecode\n(%s)\n",
+             cache_idecode_formal);
+  else
     lf_printf(file, "INLINE_IDECODE unsigned_word\nidecode_issue\n(%s)\n",
              insn_formal);
-  else if (idecode_cache)
-    lf_printf(file, "INLINE_IDECODE idecode_semantic *\nidecode\n(%s)\n",
-             idecode_cache == 1 ? insn_formal : cache_idecode_formal);
   lf_printf(file, "{\n");
   lf_indent(file, +2);
   if (!idecode_cache)