sim: ppc: netbsd: Sync errno codes with NetBSD 9.99.49
[deliverable/binutils-gdb.git] / sim / ppc / gen-idecode.c
index 1c4c6bf58a52214f38cb7adf03337f657115ef98..256ba7586b89b6e19ce5da69abe84e5b337086f8 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 1994, 1995, 1996, 1997, 2003 Andrew Cagney
 
     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/>.
  
     */
 
@@ -42,6 +41,7 @@ lf_print_opcodes(lf *file,
 {
   if (table != NULL) {
     while (1) {
+      ASSERT(table->opcode != NULL);
       lf_printf(file, "_%d_%d",
                table->opcode->first,
                table->opcode->last);
@@ -70,27 +70,7 @@ print_idecode_table(lf *file,
                    insn_table *entry,
                    const char *result)
 {
-  /* int can_assume_leaf; */
-  decode_table *opcode_rule;
-
-  /* have a look at the rule table, if all table rules follow all
-     switch rules, I can assume that all end points are leaves */
-  opcode_rule = entry->opcode_rule;
-  while (opcode_rule != NULL
-        && (opcode_rule->gen == switch_gen
-            || opcode_rule->gen == padded_switch_gen))
-    opcode_rule = opcode_rule->next;
-
-#if 0
-  /* FIXME: I don't get this bit! */
-  while (opcode_rule != NULL
-        && (opcode_rule->gen == switch_gen
-            || opcode_rule->gen == padded_switch_gen)
-        && opcode_rule->type != normal_decode_rule)
-    opcode_rule = opcode_rule->next;
-  can_assume_leaf = opcode_rule == NULL;
-#endif
-
+  lf_printf(file, "/* prime the search */\n");
   lf_printf(file, "idecode_table_entry *table = ");
   lf_print_table_name(file, entry);
   lf_printf(file, ";\n");
@@ -98,52 +78,46 @@ print_idecode_table(lf *file,
            i2target(hi_bit_nr, entry->opcode->first),
            i2target(hi_bit_nr, entry->opcode->last));
   lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
+
+  lf_printf(file, "\n");
+  lf_printf(file, "/* iterate until a leaf */\n");
   lf_printf(file, "while (1) {\n");
-  lf_indent(file, +2);
-  {
-    lf_printf(file, "/* nonzero mask -> another table */\n");
-    lf_printf(file, "while (table_entry->shift >= 0) {\n");
-    lf_indent(file, +2);
-    {
-      lf_printf(file, "table = ((idecode_table_entry*)\n");
-      lf_printf(file, "         table_entry->function_or_table);\n");
-      lf_printf(file, "opcode = ((instruction & table_entry->mask)\n");
-      lf_printf(file, "          >> table_entry->shift);\n");
-      lf_printf(file, "table_entry = table + opcode;\n");
-    }
-    lf_indent(file, -2);
-    lf_printf(file, "}\n");
-    lf_printf(file, "ASSERT(table_entry->shift < 0);\n");
-    lf_printf(file, "/* found the leaf */\n");
-    lf_printf(file, "if (table_entry->shift == table_function_entry) {\n");
-    lf_indent(file, +2);
-    if ((code & generate_jumps)) {
-      lf_printf(file, "goto *table_entry->function_or_table;\n");
+  lf_printf(file, "  signed shift = table_entry->shift;\n");
+  lf_printf(file, "if (shift == function_entry) break;\n");
+  lf_printf(file, "  if (shift >= 0) {\n");
+  lf_printf(file, "    table = ((idecode_table_entry*)\n");
+  lf_printf(file, "             table_entry->function_or_table);\n");
+  lf_printf(file, "    opcode = ((instruction & table_entry->mask)\n");
+  lf_printf(file, "              >> shift);\n");
+  lf_printf(file, "    table_entry = table + opcode;\n");
+  lf_printf(file, "  }\n");
+  lf_printf(file, "  else {\n");
+  lf_printf(file, "    /* must be a boolean */\n");
+  lf_printf(file, "    ASSERT(table_entry->shift == boolean_entry);\n");
+  lf_printf(file, "    opcode = ((instruction & table_entry->mask)\n");
+  lf_printf(file, "              != table_entry->value);\n");
+  lf_printf(file, "    table = ((idecode_table_entry*)\n");
+  lf_printf(file, "             table_entry->function_or_table);\n");
+  lf_printf(file, "    table_entry = table + opcode;\n");
+  lf_printf(file, "  }\n");
+  lf_printf(file, "}\n");
+
+  lf_printf(file, "\n");
+  lf_printf(file, "/* call the leaf code */\n");
+  if ((code & generate_jumps)) {
+    lf_printf(file, "goto *table_entry->function_or_table;\n");
+  }
+  else {
+    lf_printf(file, "%s ", result);
+    if ((code & generate_with_icache)) {
+      lf_printf(file, "(((idecode_icache*)table_entry->function_or_table)\n");
+      lf_printf(file, "  (%s));\n", ICACHE_FUNCTION_ACTUAL);
     }
     else {
-      lf_printf(file, "%s ", result);
-      if ((code & generate_with_icache)) {
-       lf_printf(file, "(((idecode_icache*)table_entry->function_or_table)\n");
-       lf_printf(file, "  (%s));\n", ICACHE_FUNCTION_ACTUAL);
-      }
-      else {
-       lf_printf(file, "((idecode_semantic*)table_entry->function_or_table)\n");
-       lf_printf(file, "  (%s);\n", SEMANTIC_FUNCTION_ACTUAL);
-      }
+      lf_printf(file, "((idecode_semantic*)table_entry->function_or_table)\n");
+      lf_printf(file, "  (%s);\n", SEMANTIC_FUNCTION_ACTUAL);
     }
-    lf_printf(file, "break;\n");
-    lf_indent(file, -2);
-    lf_printf(file, "}\n");
-    lf_printf(file, "/* must be a boolean */\n");
-    lf_printf(file, "opcode = (((instruction << table_entry->left)\n");
-    lf_printf(file, "           >> table_entry->right)\n");
-    lf_printf(file, "          != table_entry->mask);\n");
-    lf_printf(file, "table = ((idecode_table_entry*)\n");
-    lf_printf(file, "         table_entry->function_or_table);\n");
-    lf_printf(file, "table_entry = table + opcode;\n");
   }
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
 }
 
 
@@ -175,9 +149,10 @@ print_idecode_table_leaf(insn_table *entry,
 
   /* add an entry to the table */
   if (entry->parent->opcode_rule->gen == array_gen) {
+    lf_printf(file, "  /*%d*/ { ", entry->opcode_nr);
     if (entry->opcode == NULL) {
       /* table leaf entry */
-      lf_printf(file, "  /*%d*/ { table_function_entry, 0, 0, 0, ", entry->opcode_nr);
+      lf_printf(file, "function_entry, 0, 0, ");
       if ((code & generate_jumps))
        lf_printf(file, "&&");
       print_function_name(file,
@@ -186,34 +161,38 @@ print_idecode_table_leaf(insn_table *entry,
                          ((code & generate_with_icache)
                           ? function_name_prefix_icache
                           : function_name_prefix_semantics));
-      lf_printf(file, " },\n");
     }
     else if (entry->opcode_rule->gen == switch_gen
+            || entry->opcode_rule->gen == goto_switch_gen
             || entry->opcode_rule->gen == padded_switch_gen) {
       /* table calling switch statement */
-      lf_printf(file, "  /*%d*/ { table_function_entry, 0, 0, 0, ",
-               entry->opcode_nr);
+      lf_printf(file, "function_entry, 0, 0, ");
       if ((code & generate_jumps))
        lf_printf(file, "&&");
       lf_print_table_name(file, entry);
-      lf_printf(file, " },\n");
+    }
+    else if (entry->opcode->is_boolean) {
+      /* table `calling' boolean table */
+      lf_printf(file, "boolean_entry, ");
+      lf_printf(file, "MASK32(%d, %d), ",
+               i2target(hi_bit_nr, entry->opcode->first),
+               i2target(hi_bit_nr, entry->opcode->last));
+      lf_printf(file, "INSERTED32(%d, %d, %d), ",
+               entry->opcode->boolean_constant,
+               i2target(hi_bit_nr, entry->opcode->first),
+               i2target(hi_bit_nr, entry->opcode->last));
+      lf_print_table_name(file, entry);
     }
     else {
       /* table `calling' another table */
-      lf_printf(file, "  /*%d*/ { ", entry->opcode_nr);
-      if (entry->opcode->is_boolean)
-       lf_printf(file, "table_boolean_entry, %d, %d, %d, ",
-                 entry->opcode->first,
-                 insn_bit_size - entry->opcode->last + entry->opcode->first - 1,
-                 entry->opcode->boolean_constant);
-      else
-       lf_printf(file, "%d, 0, 0, MASK32(%d,%d), ",
-                 insn_bit_size - entry->opcode->last - 1,
-                 i2target(hi_bit_nr, entry->opcode->first),
-                 i2target(hi_bit_nr, entry->opcode->last));
+      lf_printf(file, "%d, ", insn_bit_size - entry->opcode->last - 1);
+      lf_printf(file, "MASK32(%d,%d), ",
+               i2target(hi_bit_nr, entry->opcode->first),
+               i2target(hi_bit_nr, entry->opcode->last));
+      lf_printf(file, "0, ");
       lf_print_table_name(file, entry);
-      lf_printf(file, " },\n");
     }
+    lf_printf(file, " },\n");
   }
 }
 
@@ -238,7 +217,7 @@ print_idecode_table_padding(insn_table *table,
 {
   ASSERT(depth == 0);
   if (table->opcode_rule->gen == array_gen) {
-    lf_printf(file, "  /*%d*/ { table_function_entry, 0, 0, 0, ", opcode_nr);
+    lf_printf(file, "  /*%d*/ { function_entry, 0, 0, ", opcode_nr);
     if ((code & generate_jumps))
       lf_printf(file, "&&");
     lf_printf(file, "%s_illegal },\n",
@@ -250,12 +229,89 @@ print_idecode_table_padding(insn_table *table,
 /****************************************************************/
 
 
+static void
+print_goto_switch_name(lf *file,
+                      insn_table *entry)
+{
+  lf_printf(file, "case_");
+  if (entry->opcode == NULL)
+    print_function_name(file,
+                       entry->insns->file_entry->fields[insn_name],
+                       entry->expanded_bits,
+                       ((code & generate_with_icache)
+                        ? function_name_prefix_icache
+                        : function_name_prefix_semantics));
+  else
+    lf_print_table_name(file, entry);
+}
+
+static void
+print_goto_switch_table_leaf(insn_table *entry,
+                            lf *file,
+                            void *data,
+                            insn *instruction,
+                            int depth)
+{
+  ASSERT(entry->parent != NULL);
+  ASSERT(depth == 0);
+  ASSERT(entry->parent->opcode_rule->gen == goto_switch_gen);
+  ASSERT(entry->parent->opcode);
+
+  lf_printf(file, "&&");
+  print_goto_switch_name(file, entry);
+  lf_printf(file, ",\n");
+}
+
+static void
+print_goto_switch_table_padding(insn_table *table,
+                               lf *file,
+                               void *data,
+                               int depth,
+                               int opcode_nr)
+{
+  ASSERT(depth == 0);
+  ASSERT(table->opcode_rule->gen == goto_switch_gen);
+
+  lf_printf(file, "&&illegal_");
+  lf_print_table_name(file, table);
+  lf_printf(file, ",\n");
+}
+
+static void
+print_goto_switch_break(lf *file,
+                       insn_table *entry)
+{
+  lf_printf(file, "goto break_");
+  lf_print_table_name(file, entry->parent);
+  lf_printf(file, ";\n");
+}
+
+
+static void
+print_goto_switch_table(lf *file,
+                       insn_table *table)
+{
+  lf_printf(file, "const static void *");
+  lf_print_table_name(file, table);
+  lf_printf(file, "[] = {\n");
+  lf_indent(file, +2);
+  insn_table_traverse_tree(table,
+                          file, NULL/*data*/,
+                          0,
+                          NULL/*start*/,
+                          print_goto_switch_table_leaf,
+                          NULL/*end*/,
+                          print_goto_switch_table_padding);
+  lf_indent(file, -2);
+  lf_printf(file, "};\n");
+}
+
+
 void print_idecode_switch
 (lf *file, 
  insn_table *table,
  const char *result);
 
-
 static void
 idecode_switch_start(insn_table *table,
                     lf *file,
@@ -265,15 +321,39 @@ idecode_switch_start(insn_table *table,
   /* const char *result = data; */
   ASSERT(depth == 0);
   ASSERT(table->opcode_rule->gen == switch_gen
-        || table->opcode_rule->gen == padded_switch_gen
-        || table->opcode_rule->gen == goto_gen);
+        || table->opcode_rule->gen == goto_switch_gen
+        || table->opcode_rule->gen == padded_switch_gen);
 
-  switch (table->opcode_rule->gen) {
-  default:
+  if (table->opcode->is_boolean
+      || table->opcode_rule->gen == switch_gen
+        || table->opcode_rule->gen == padded_switch_gen) {
     lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
              i2target(hi_bit_nr, table->opcode->first),
              i2target(hi_bit_nr, table->opcode->last));
-    break;
+  }
+  else if (table->opcode_rule->gen == goto_switch_gen) {
+    if (table->parent != NULL
+       && (table->parent->opcode_rule->gen == switch_gen
+           || table->parent->opcode_rule->gen == goto_switch_gen
+           || table->parent->opcode_rule->gen == padded_switch_gen)) {
+      lf_printf(file, "{\n");
+      lf_indent(file, +2);
+    }
+    print_goto_switch_table(file, table);
+    lf_printf(file, "ASSERT(EXTRACTED32(instruction, %d, %d)\n",
+             i2target(hi_bit_nr, table->opcode->first),
+             i2target(hi_bit_nr, table->opcode->last));
+    lf_printf(file, "       < (sizeof(");
+    lf_print_table_name(file, table);
+    lf_printf(file, ") / sizeof(void*)));\n");
+    lf_printf(file, "goto *");
+    lf_print_table_name(file, table);
+    lf_printf(file, "[EXTRACTED32(instruction, %d, %d)];\n",
+             i2target(hi_bit_nr, table->opcode->first),
+             i2target(hi_bit_nr, table->opcode->last));
+  }
+  else {
+    ASSERT("bad switch" == NULL);
   }
 }
 
@@ -289,16 +369,34 @@ idecode_switch_leaf(insn_table *entry,
   ASSERT(entry->parent != NULL);
   ASSERT(depth == 0);
   ASSERT(entry->parent->opcode_rule->gen == switch_gen
+        || entry->parent->opcode_rule->gen == goto_switch_gen
         || entry->parent->opcode_rule->gen == padded_switch_gen);
   ASSERT(entry->parent->opcode);
 
   if (entry->parent->opcode->is_boolean
-      && entry->opcode_nr == 0)
+      && entry->opcode_nr == 0) {
+    /* boolean false target */
     lf_printf(file, "case %d:\n", entry->parent->opcode->boolean_constant);
-  else if (!entry->parent->opcode->is_boolean)
-    lf_printf(file, "case %d:\n", entry->opcode_nr);
-  else
+  }
+  else if (entry->parent->opcode->is_boolean
+          && entry->opcode_nr != 0) {
+    /* boolean true case */
     lf_printf(file, "default:\n");
+  }
+  else if (entry->parent->opcode_rule->gen == switch_gen
+          || entry->parent->opcode_rule->gen == padded_switch_gen) {
+    /* normal goto */
+    lf_printf(file, "case %d:\n", entry->opcode_nr);
+  }
+  else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
+    /* lf_indent(file, -1); */
+    print_goto_switch_name(file, entry);
+    lf_printf(file, ":\n");
+    /* lf_indent(file, +1); */
+  }
+  else {
+    ASSERT("bad switch" == NULL);
+  }
   lf_indent(file, +2);
   {
     if (entry->opcode == NULL) {
@@ -318,6 +416,7 @@ idecode_switch_leaf(insn_table *entry,
       lf_printf(file, ";\n");
     }
     else if (entry->opcode_rule->gen == switch_gen
+            || entry->opcode_rule->gen == goto_switch_gen
             || entry->opcode_rule->gen == padded_switch_gen) {
       /* switch calling switch */
       print_idecode_switch(file, entry, result);
@@ -330,7 +429,17 @@ idecode_switch_leaf(insn_table *entry,
       lf_indent(file, -2);
       lf_printf(file, "}\n");
     }
-    lf_printf(file, "break;\n");
+    if (entry->parent->opcode->is_boolean
+       || entry->parent->opcode_rule->gen == switch_gen
+       || entry->parent->opcode_rule->gen == padded_switch_gen) {
+      lf_printf(file, "break;\n");
+    }
+    else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
+      print_goto_switch_break(file, entry);
+    }
+    else {
+      ASSERT("bad switch" == NULL);
+    }
   }
   lf_indent(file, -2);
 }
@@ -342,7 +451,7 @@ print_idecode_switch_illegal(lf *file,
 {
   lf_indent(file, +2);
   print_idecode_illegal(file, result);
-  /*lf_printf(file, "break;\n");*/
+  lf_printf(file, "break;\n");
   lf_indent(file, -2);
 }
 
@@ -355,11 +464,15 @@ idecode_switch_end(insn_table *table,
   const char *result = data;
   ASSERT(depth == 0);
   ASSERT(table->opcode_rule->gen == switch_gen
-        || table->opcode_rule->gen == padded_switch_gen
-        || table->opcode_rule->gen == goto_gen);
+        || table->opcode_rule->gen == goto_switch_gen
+        || table->opcode_rule->gen == padded_switch_gen);
   ASSERT(table->opcode);
 
-  if (!table->opcode->is_boolean) {
+  if (table->opcode->is_boolean) {
+    lf_printf(file, "}\n");
+  }
+  else if (table->opcode_rule->gen == switch_gen
+          || table->opcode_rule->gen == padded_switch_gen) {
     lf_printf(file, "default:\n");
     switch (table->opcode_rule->gen) {
     case switch_gen:
@@ -370,10 +483,29 @@ idecode_switch_end(insn_table *table,
       lf_printf(file, "  break;\n");
       break;
     default:
-      error("idecode_switch_end - unknown switch type\n");
+      ASSERT("bad switch" == NULL);
     }
+    lf_printf(file, "}\n");
+  }
+  else if (table->opcode_rule->gen == goto_switch_gen) {
+    lf_printf(file, "illegal_");
+    lf_print_table_name(file, table);
+    lf_printf(file, ":\n");
+    print_idecode_illegal(file, result);
+    lf_printf(file, "break_");
+    lf_print_table_name(file, table);
+    lf_printf(file, ":;\n");
+    if (table->parent != NULL
+       && (table->parent->opcode_rule->gen == switch_gen
+           || table->parent->opcode_rule->gen == goto_switch_gen
+           || table->parent->opcode_rule->gen == padded_switch_gen)) {
+      lf_indent(file, -2);
+      lf_printf(file, "}\n");
+    }
+  }
+  else {
+    ASSERT("bad switch" == NULL);
   }
-  lf_printf(file, "}\n");
 }
 
 static void
@@ -386,15 +518,21 @@ idecode_switch_padding(insn_table *table,
   const char *result = data;
   ASSERT(depth == 0);
   ASSERT(table->opcode_rule->gen == switch_gen
+        || table->opcode_rule->gen == goto_switch_gen
         || table->opcode_rule->gen == padded_switch_gen);
 
-  if (table->opcode_rule->gen == padded_switch_gen) {
+  switch (table->opcode_rule->gen) {
+  case switch_gen:
+    break;
+  case padded_switch_gen:
     lf_printf(file, "case %d:\n", opcode_nr);
     print_idecode_switch_illegal(file, result);
-  }
-  else if (table->opcode_rule->gen == goto_gen) {
-    lf_printf(file, "goto_%d:\n", opcode_nr);
-    print_idecode_switch_illegal(file, result);
+    break;
+  case goto_switch_gen:
+    /* no padding needed */
+    break;
+  default:
+    ASSERT("bad switch" != NULL);
   }
 }
 
@@ -452,12 +590,13 @@ idecode_declare_if_switch(insn_table *table,
                          int depth)
 {
   if ((table->opcode_rule->gen == switch_gen
+       || table->opcode_rule->gen == goto_switch_gen
        || table->opcode_rule->gen == padded_switch_gen)
       && table->parent != NULL /* don't declare the top one yet */
       && table->parent->opcode_rule->gen == array_gen) {
     print_idecode_switch_function_header(file,
-                                           table,
-                                           0/*isnt function definition*/);
+                                        table,
+                                        0/*isnt function definition*/);
   }
 }
 
@@ -469,6 +608,7 @@ idecode_expand_if_switch(insn_table *table,
                         int depth)
 {
   if ((table->opcode_rule->gen == switch_gen
+       || table->opcode_rule->gen == goto_switch_gen
        || table->opcode_rule->gen == padded_switch_gen)
       && table->parent != NULL /* don't expand the top one yet */
       && table->parent->opcode_rule->gen == array_gen) {
@@ -530,20 +670,14 @@ print_idecode_lookups(lf *file,
 static void
 print_idecode_body(lf *file,
                   insn_table *table,
-                  const char *result,
-                  const char *indent)
+                  const char *result)
 {
-  lf_indent(file, +strlen(indent));
-  lf_putstr(file, "{\n");
-  lf_indent(file, +2);
   if (table->opcode_rule->gen == switch_gen
+      || table->opcode_rule->gen == goto_switch_gen
       || table->opcode_rule->gen == padded_switch_gen)
     print_idecode_switch(file, table, result);
   else
     print_idecode_table(file, table, result);
-  lf_indent(file, -2);
-  lf_putstr(file, "}\n");
-  lf_indent(file, -strlen(indent));
 }
 
 
@@ -565,79 +699,122 @@ print_run_until_stop_body(lf *file,
 
   lf_putstr(file, "{\n");
   lf_indent(file, +2);
-  if (!can_stop)
-    lf_putstr(file, "int *keep_running = NULL;\n");
   lf_putstr(file, "jmp_buf halt;\n");
   lf_putstr(file, "jmp_buf restart;\n");
-  lf_putstr(file, "cpu *processor = NULL;\n");
-  lf_putstr(file, "unsigned_word cia = -1;\n");
-  lf_putstr(file, "instruction_word instruction = 0;\n");
-  if (generate_smp) {
-    lf_putstr(file, "int current_cpu = -1;\n");
+  if (!generate_smp) {
+    lf_putstr(file, "cpu *processor = NULL;\n");
+    lf_putstr(file, "unsigned_word cia = -1;\n");
   }
-  if ((code & generate_with_icache)) {
-    lf_putstr(file, "idecode_cache *cache_entry = NULL;\n");
+  lf_putstr(file, "int last_cpu;\n");
+  if (generate_smp) {
+    lf_putstr(file, "int current_cpu;\n");
   }
 
   if ((code & generate_with_icache)) {
+    lf_putstr(file, "int cpu_nr;\n");
     lf_putstr(file, "\n");
-    lf_putstr(file, "{\n");
-    lf_putstr(file, "  int cpu_nr;\n");
-    lf_putstr(file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
-    lf_putstr(file, "    cpu_flush_icache(processors[cpu_nr]);\n");
-    lf_putstr(file, "}\n");
+    lf_putstr(file, "/* flush the icache of a possible break insn */\n");
+    lf_putstr(file, "for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
+    lf_putstr(file, "  cpu_flush_icache(processors[cpu_nr]);\n");
   }
 
   lf_putstr(file, "\n");
-  lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
-
-  lf_putstr(file, "\n");
+  lf_putstr(file, "/* set the halt target initially */\n");
+  lf_putstr(file, "psim_set_halt_and_restart(system, &halt, NULL);\n");
   lf_putstr(file, "if (setjmp(halt))\n");
   lf_putstr(file, "  return;\n");
 
   lf_putstr(file, "\n");
-  lf_putstr(file, "setjmp(restart);\n");
+  lf_putstr(file, "/* where were we before the halt? */\n");
+  lf_putstr(file, "last_cpu = psim_last_cpu(system);\n");
 
-  if (!generate_smp) {
+  lf_putstr(file, "\n");
+  lf_putstr(file, "/* check for need to force event processing first */\n");
+  lf_putstr(file, "if (WITH_EVENTS) {\n");
+  lf_putstr(file, "  if (last_cpu == nr_cpus) {\n");
+  lf_putstr(file, "    /* halted during event processing */\n");
+  lf_putstr(file, "    event_queue_process(events);\n");
+  lf_putstr(file, "    last_cpu = -1;\n");
+  lf_putstr(file, "  }\n");
+  lf_putstr(file, "  else if (last_cpu == nr_cpus - 1) {\n");
+  lf_putstr(file, "    /* last cpu did halt */\n");
+  lf_putstr(file, "    if (event_queue_tick(events)) {\n");
+  lf_putstr(file, "      event_queue_process(events);\n");
+  lf_putstr(file, "    }\n");
+  lf_putstr(file, "    last_cpu = -1;\n");
+  lf_putstr(file, "  }\n");
+  lf_putstr(file, "}\n");
+  lf_putstr(file, "else {\n");
+  lf_putstr(file, " if (last_cpu == nr_cpus - 1)\n");
+  lf_putstr(file, "   /* cpu zero is next */\n");
+  lf_putstr(file, "   last_cpu = -1;\n");
+  lf_putstr(file, "}\n");
 
-    lf_putstr(file, "
-/* CASE 1: NO SMP (with or with out instruction cache).
+  lf_putstr(file, "\n");
+  lf_putstr(file, "/* have ensured that the event queue can not be first */\n");
+  lf_putstr(file, "ASSERT(last_cpu >= -1 && last_cpu < nr_cpus - 1);\n");
+
+  if (!generate_smp) {
 
-   In this case, we can take advantage of the fact that the current
-   instruction address does not need to be returned to the cpu object
-   after every execution of an instruction.  Instead it only needs to
-   be saved when either A. the main loop exits or B. A cpu-halt or
-   cpu-restart call forces the loop to be re-enered.  The later
-   functions always save the current cpu instruction address.
+    lf_putstr(file, "\n\
+/* CASE 1: NO SMP (with or with out instruction cache).\n\
+\n\
+   In this case, we can take advantage of the fact that the current\n\
+   instruction address does not need to be returned to the cpu object\n\
+   after every execution of an instruction.  Instead it only needs to\n\
+   be saved when either A. the main loop exits or B. A cpu-halt or\n\
+   cpu-restart call forces the loop to be re-enered.  The later\n\
+   functions always save the current cpu instruction address.\n\
+\n\
+   Two subcases also exist that with and that without an instruction\n\
+   cache.\n\
+\n\
+   An additional complexity is the need to ensure that a 1:1 ratio\n\
+   is maintained between the execution of an instruction and the\n\
+   incrementing of the simulation clock */");
 
-   Two subcases also exist that with and that without an instruction
-   cache. */");
+    lf_putstr(file, "\n");
 
-    lf_putstr(file, "\n\n");
+    lf_putstr(file, "\n");
+    lf_putstr(file, "/* now add restart target as ready to run */\n");
+    lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
+    lf_putstr(file, "if (setjmp(restart)) {\n");
+    lf_putstr(file, "  if (WITH_EVENTS) {\n");
+    lf_putstr(file, "    /* when restart, cpu must have been last, clock next */\n");
+    lf_putstr(file, "    if (event_queue_tick(events)) {\n");
+    lf_putstr(file, "      event_queue_process(events);\n");
+    lf_putstr(file, "    }\n");
+    lf_putstr(file, "  }\n");
+    lf_putstr(file, "}\n");
 
+    lf_putstr(file, "\n");
+    lf_putstr(file, "/* prime the main loop */\n");
     lf_putstr(file, "processor = processors[0];\n");
     lf_putstr(file, "cia = cpu_get_program_counter(processor);\n");
+
+    lf_putstr(file, "\n");
     lf_putstr(file, "while (1) {\n");
     lf_indent(file, +2);
-    lf_putstr(file, "if (WITH_EVENTS) {\n");
-    lf_putstr(file, "  if (event_queue_tick(events)) {\n");
-    lf_putstr(file, "    cpu_set_program_counter(processor, cia);\n");
-    lf_putstr(file, "    event_queue_process(events);\n");
-    lf_putstr(file, "    cia = cpu_get_program_counter(processor);\n");
-    lf_putstr(file, "  }\n");
-    lf_putstr(file, "}\n");
 
     if (!(code & generate_with_icache)) {
-      lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
-      print_idecode_body(file, table, "cia =", "");
+      lf_putstr(file, "instruction_word instruction =\n");
+      lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
+      lf_putstr(file, "\n");
+      print_idecode_body(file, table, "cia =");;
     }
 
     if ((code & generate_with_icache)) {
-      lf_putstr(file, "cache_entry = cpu_icache_entry(processor, cia);\n");
+      lf_putstr(file, "idecode_cache *cache_entry =\n");
+      lf_putstr(file, "  cpu_icache_entry(processor, cia);\n");
       lf_putstr(file, "if (cache_entry->address == cia) {\n");
       lf_putstr(file, "  /* cache hit */\n");
       lf_putstr(file, "  idecode_semantic *const semantic = cache_entry->semantic;\n");
       lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
+      /* tail */
+      if (can_stop) {
+       lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+       lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+      }
       lf_putstr(file, "}\n");
       lf_putstr(file, "else {\n");
       lf_putstr(file, "  /* cache miss */\n");
@@ -646,40 +823,77 @@ print_run_until_stop_body(lf *file,
        lf_putstr(file, "idecode_semantic *semantic;\n");
        lf_indent(file, -2);
       }
-      lf_putstr(file, "  instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
+      lf_putstr(file, "  instruction_word instruction =\n");
+      lf_putstr(file, "    vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
       lf_putstr(file, "  if (WITH_MON != 0)\n");
       lf_putstr(file, "    mon_event(mon_event_icache_miss, processor, cia);\n");
       if ((code & generate_with_semantic_icache)) {
-       print_idecode_body(file, table, "cia =", "  ");
+       lf_putstr(file, "{\n");
+       lf_indent(file, +2);
+       print_idecode_body(file, table, "cia =");
+       lf_indent(file, -2);
+       lf_putstr(file, "}\n");
       }
       else {
-       print_idecode_body(file, table, "semantic =", "  ");
+       print_idecode_body(file, table, "semantic =");
        lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
       }
       lf_putstr(file, "}\n");
     }
 
-    lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
-    lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+    /* events */
+    lf_putstr(file, "\n");
+    lf_putstr(file, "/* process any events */\n");
+    lf_putstr(file, "if (WITH_EVENTS) {\n");
+    lf_putstr(file, "  if (event_queue_tick(events)) {\n");
+    lf_putstr(file, "    cpu_set_program_counter(processor, cia);\n");
+    lf_putstr(file, "    event_queue_process(events);\n");
+    lf_putstr(file, "    cia = cpu_get_program_counter(processor);\n");
+    lf_putstr(file, "  }\n");
+    lf_putstr(file, "}\n");
+
+    /* tail */
+    if (can_stop) {
+      lf_putstr(file, "\n");
+      lf_putstr(file, "/* abort if necessary */\n");
+      lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+      lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*not important*/);\n");
+    }
+
     lf_indent(file, -2);
     lf_putstr(file, "}\n");
   }
     
   if (generate_smp) {
 
-    lf_putstr(file, "
-/* CASE 2: SMP (With or without ICACHE)
-
-   The complexity here comes from needing to correctly restart the
-   system when it is aborted.  In particular if cpu0 requests a
-   restart, the next cpu is still cpu1.  Cpu0 being restarted after
+    lf_putstr(file, "\n\
+/* CASE 2: SMP (With or without ICACHE)\n\
+\n\
+   The complexity here comes from needing to correctly restart the\n\
+   system when it is aborted.  In particular if cpu0 requests a\n\
+   restart, the next cpu is still cpu1.  Cpu0 being restarted after\n\
    all the other CPU's and the event queue have been processed */");
 
-    lf_putstr(file, "\n\n");
+    lf_putstr(file, "\n");
+
+    lf_putstr(file, "\n");
+    lf_putstr(file, "/* now establish the restart target */\n");
+    lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
+    lf_putstr(file, "if (setjmp(restart)) {\n");
+    lf_putstr(file, "  current_cpu = psim_last_cpu(system);\n");
+    lf_putstr(file, "  ASSERT(current_cpu >= 0 && current_cpu < nr_cpus);\n");
+    lf_putstr(file, "}\n");
+    lf_putstr(file, "else {\n");
+    lf_putstr(file, "  current_cpu = last_cpu;\n");
+    lf_putstr(file, "  ASSERT(current_cpu >= -1 && current_cpu < nr_cpus);\n");
+    lf_putstr(file, "}\n");
+    
 
-    lf_putstr(file, "current_cpu = psim_last_cpu(system);\n");
+    lf_putstr(file, "\n");
     lf_putstr(file, "while (1) {\n");
     lf_indent(file, +2);
+
+    lf_putstr(file, "\n");
     lf_putstr(file, "if (WITH_EVENTS) {\n");
     lf_putstr(file, "  current_cpu += 1;\n");
     lf_putstr(file, "  if (current_cpu == nr_cpus) {\n");
@@ -692,47 +906,86 @@ print_run_until_stop_body(lf *file,
     lf_putstr(file, "else {\n");
     lf_putstr(file, "  current_cpu = (current_cpu + 1) % nr_cpus;\n");
     lf_putstr(file, "}\n");
-    lf_putstr(file, "processor = processors[current_cpu];\n");
-    lf_putstr(file, "cia = cpu_get_program_counter(processor);\n");
+
+    lf_putstr(file, "\n");
+    lf_putstr(file, "{\n");
+    lf_indent(file, +2);
+    lf_putstr(file, "cpu *processor = processors[current_cpu];\n");
+    lf_putstr(file, "unsigned_word cia =\n");
+    lf_putstr(file, "  cpu_get_program_counter(processor);\n");
 
     if (!(code & generate_with_icache)) {
-      lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
-      print_idecode_body(file, table, "cia =", "");
+      lf_putstr(file, "instruction_word instruction =\n");
+      lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
+      print_idecode_body(file, table, "cia =");
+      if (can_stop) {
+       lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+       lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+      }
+      lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
     }
 
     if ((code & generate_with_icache)) {
-      lf_putstr(file, "cache_entry = cpu_icache_entry(processor, cia);\n");
+      lf_putstr(file, "idecode_cache *cache_entry =\n");
+      lf_putstr(file, "  cpu_icache_entry(processor, cia);\n");
+      lf_putstr(file, "\n");
       lf_putstr(file, "if (cache_entry->address == cia) {\n");
-      lf_putstr(file, "  /* cache hit */\n");
-      lf_putstr(file, "  idecode_semantic *semantic = cache_entry->semantic;\n");
-      lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
-      lf_putstr(file, "}\n");
-      lf_putstr(file, "else {\n");
-      lf_putstr(file, "  /* cache miss */\n");
-      if (!(code & generate_with_semantic_icache)) {
+      {
        lf_indent(file, +2);
-       lf_putstr(file, "  idecode_semantic *semantic;\n");
+       lf_putstr(file, "\n");
+       lf_putstr(file, "/* cache hit */\n");
+       lf_putstr(file, "idecode_semantic *semantic = cache_entry->semantic;\n");
+       lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
+       /* tail */
+       if (can_stop) {
+         lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+         lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
+       }
+       lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+       lf_putstr(file, "\n");
        lf_indent(file, -2);
       }
-      lf_putstr(file, "  instruction =\n");
-      lf_putstr(file, "    vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
-      lf_putstr(file, "  if (WITH_MON != 0)\n");
-      lf_putstr(file, "    mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
-      if ((code & generate_with_semantic_icache)) {
-       print_idecode_body(file, table, "cia =", "  ");
-      }
-      else {
-       print_idecode_body(file, table, "semantic = ", "  ");
+      lf_putstr(file, "}\n");
+      lf_putstr(file, "else {\n");
+      {
        lf_indent(file, +2);
-       lf_putstr(file, "cia = semantic(processor, cache_entry, cia));\n");
+       lf_putstr(file, "\n");
+       lf_putstr(file, "/* cache miss */\n");
+       if (!(code & generate_with_semantic_icache)) {
+         lf_putstr(file, "idecode_semantic *semantic;\n");
+       }
+       lf_putstr(file, "instruction_word instruction =\n");
+       lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
+       lf_putstr(file, "if (WITH_MON != 0)\n");
+       lf_putstr(file, "  mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
+       if ((code & generate_with_semantic_icache)) {
+         lf_putstr(file, "{\n");
+         lf_indent(file, +2);
+         print_idecode_body(file, table, "cia =");
+         lf_indent(file, -2);
+         lf_putstr(file, "}\n");
+       }
+       else {
+         print_idecode_body(file, table, "semantic = ");
+         lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
+       }
+       /* tail */
+       if (can_stop) {
+         lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+         lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
+       }
+       lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+       lf_putstr(file, "\n");
        lf_indent(file, -2);
       }
       lf_putstr(file, "}\n");
     }
 
-    lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
-    lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
-    lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+    /* close */
+    lf_indent(file, -2);
+    lf_putstr(file, "}\n");
+
+    /* tail */
     lf_indent(file, -2);
     lf_putstr(file, "}\n");
   }
@@ -765,10 +1018,11 @@ print_jump(lf *file,
   }
 
   if (generate_smp) {
-    lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
+    if (is_tail)
+      lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
     lf_putstr(file, "if (WITH_EVENTS) {\n");
     lf_putstr(file, "  current_cpu += 1;\n");
-    lf_putstr(file, "  if (current_cpu == nr_cpus) {\n");
+    lf_putstr(file, "  if (current_cpu >= nr_cpus) {\n");
     lf_putstr(file, "    if (event_queue_tick(events)) {\n");
     lf_putstr(file, "      event_queue_process(events);\n");
     lf_putstr(file, "    }\n");
@@ -793,7 +1047,7 @@ print_jump(lf *file,
     }
   }
 
-  if (!(code & generate_with_icache)) {
+  if (!(code & generate_with_icache) && is_tail) {
     lf_printf(file, "goto idecode;\n");
   }
 
@@ -813,7 +1067,7 @@ print_jump_insn(lf *file,
 
   /* what we are for the moment */
   lf_printf(file, "\n");
-  print_define_my_index(file, instruction->file_entry);
+  print_my_defines(file, expanded_bits, instruction->file_entry);
 
   /* output the icache entry */
   if ((code & generate_with_icache)) {
@@ -837,9 +1091,8 @@ print_jump_insn(lf *file,
                      instruction,
                      expanded_bits,
                      cache_rules,
-                     0,
-                     0/*get_value_from_cache*/,
-                     1/*put_value_in_cache*/);
+                     0, /*use_defines*/
+                     put_values_in_icache);
     lf_printf(file, "cache_entry->address = nia;\n");
     lf_printf(file, "cache_entry->semantic = &&");
     print_function_name(file,
@@ -884,13 +1137,25 @@ print_jump_insn(lf *file,
                    instruction,
                    expanded_bits,
                    cache_rules,
-                   (code & generate_with_direct_access_icache),
-                   (code & generate_with_icache)/*get_value_from_cache*/,
-                   0/*put_value_in_cache*/);
+                   ((code & generate_with_direct_access)
+                    ? define_variables
+                    : declare_variables),
+                   ((code & generate_with_icache)
+                    ? get_values_from_icache
+                    : do_not_use_icache));
   print_semantic_body(file,
                      instruction,
                      expanded_bits,
                      opcodes);
+  if (code & generate_with_direct_access)
+    print_icache_body(file,
+                     instruction,
+                     expanded_bits,
+                     cache_rules,
+                     undef_variables,
+                     ((code & generate_with_icache)
+                      ? get_values_from_icache
+                      : do_not_use_icache));
   print_jump(file, 1/*is tail*/);
   lf_indent(file, -2);
   lf_printf(file, "}\n");
@@ -1031,7 +1296,7 @@ print_jump_until_stop_body(lf *file,
   lf_putstr(file, "instruction\n");
   lf_putstr(file, "  = vm_instruction_map_read(cpu_instruction_map(processor),\n");
   lf_putstr(file, "                            processor, nia);\n");
-  print_idecode_body(file, table, "/*IGORE*/", "");
+  print_idecode_body(file, table, "/*IGORE*/");
 
   /* print out a table of all the internals functions */
   insn_table_traverse_function(table,
@@ -1182,7 +1447,7 @@ print_idecode_run_function_header(lf *file,
 {
   int indent;
   lf_printf(file, "\n");
-  lf_print_function_type(file, "void", "INLINE_IDECODE", (is_definition ? " " : "\n"));
+  lf_print_function_type(file, "void", "PSIM_INLINE_IDECODE", (is_definition ? " " : "\n"));
   indent = lf_putstr(file, (can_stop ? "idecode_run_until_stop" : "idecode_run"));
   if (is_definition)
     lf_putstr(file, "\n");
@@ -1233,21 +1498,24 @@ gen_idecode_c(lf *file,
   lf_printf(file, "#include \"idecode.h\"\n");
   lf_printf(file, "#include \"semantics.h\"\n");
   lf_printf(file, "#include \"icache.h\"\n");
+  lf_printf(file, "#ifdef HAVE_COMMON_FPU\n");
+  lf_printf(file, "#include \"sim-inline.h\"\n");
+  lf_printf(file, "#include \"sim-fpu.h\"\n");
+  lf_printf(file, "#endif\n");
   lf_printf(file, "#include \"support.h\"\n");
   lf_printf(file, "\n");
   lf_printf(file, "#include <setjmp.h>\n");
   lf_printf(file, "\n");
-  lf_printf(file, "/* encodings for a negative shift field */\n");
   lf_printf(file, "enum {\n");
-  lf_printf(file, "  table_boolean_entry = -2,\n");
-  lf_printf(file, "  table_function_entry = -1,\n");
+  lf_printf(file, "  /* greater or equal to zero => table */\n");
+  lf_printf(file, "  function_entry = -1,\n");
+  lf_printf(file, "  boolean_entry = -2,\n");
   lf_printf(file, "};\n");
   lf_printf(file, "\n");
   lf_printf(file, "typedef struct _idecode_table_entry {\n");
-  lf_printf(file, "  signed short shift;  /* shift >= 0: t[(i & mask) >> shift] */\n");
-  lf_printf(file, "  unsigned char left;  /* shift == -2: */\n");
-  lf_printf(file, "  unsigned char right; /*     t[((i << left) >> right) != mask] */\n");
-  lf_printf(file, "  unsigned mask;       /* else (shift == -1): function() */\n");  
+  lf_printf(file, "  int shift;\n");
+  lf_printf(file, "  instruction_word mask;\n");
+  lf_printf(file, "  instruction_word value;");
   lf_printf(file, "  void *function_or_table;\n");
   lf_printf(file, "} idecode_table_entry;\n");
   lf_printf(file, "\n");
@@ -1278,5 +1546,3 @@ gen_idecode_c(lf *file,
     error("Something is wrong!\n");
   }
 }
-
-
This page took 0.035063 seconds and 4 git commands to generate.