Minor fix to gdb.prompt documentation
[deliverable/binutils-gdb.git] / sim / ppc / igen.c
index f9940d82c9329f1a52d47d4a1e1bc4a66e597b67..5a1df3ee911df36e738ac39063c3df372c96574b 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,
     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/>.
  
     */
 
-#include <stdio.h>
-#include <ctype.h>
+
+
 #include <getopt.h>
 
 #include "misc.h"
 #include "lf.h"
 #include "table.h"
-#include "config.h"
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
-
-
-/****************************************************************/
-
-enum {
-  max_insn_size = 32,
-};
-
-static int hi_bit_nr = 0;
-static int insn_size = max_insn_size;
-static int idecode_expand_semantics = 0;
-static int idecode_cache = 0;
-static int number_lines = 1;
-
-
-/****************************************************************/
-
-
-static char *cache_idecode_formal  =
-"cpu *processor,\n\
- instruction_word instruction,\n\
- unsigned_word cia,\n\
- idecode_cache *cache_entry";
-
-static char *cache_idecode_actual = "processor, instruction, cia, cache_entry";
-
-static char *cache_semantic_formal =
-"cpu *processor,\n\
- idecode_cache *cache_entry,\n\
- unsigned_word cia";
-
-static char *semantic_formal = 
-"cpu *processor,\n\
- instruction_word instruction,\n\
- unsigned_word cia";
-
-static char *semantic_actual = "processor, instruction, cia";
-
-
-
-/****************************************************************/
-
-
-typedef struct _filter filter;
-struct _filter {
-  char *flag;
-  filter *next;
-};
-static filter *filters = NULL;
-
-
-/****************************************************************/
-
-
-typedef struct _cache_rules cache_rules;
-struct _cache_rules {
-  int valid;
-  char *old_name;
-  char *new_name;
-  char *type;
-  char *expression;
-  cache_rules *next;
-};
-static cache_rules *cache_table;
-
-
-enum {
-  ca_valid,
-  ca_old_name,
-  ca_new_name,
-  ca_type,
-  ca_expression,
-  nr_cache_rule_fields,
-};
-
-static cache_rules *
-load_cache_rules(char *file_name)
-{
-  table *file = table_open(file_name, nr_cache_rule_fields, 0);
-  table_entry *entry;
-  cache_rules *table = NULL;
-  cache_rules **curr_rule = &table;
-  while ((entry = table_entry_read(file)) != NULL) {
-    cache_rules *new_rule = ZALLOC(cache_rules);
-    new_rule->valid = target_a2i(hi_bit_nr, entry->fields[ca_valid]);
-    new_rule->old_name = entry->fields[ca_old_name];
-    new_rule->new_name = entry->fields[ca_new_name];
-    new_rule->type = (strlen(entry->fields[ca_type])
-                     ? entry->fields[ca_type]
-                     : NULL);
-    new_rule->expression = (strlen(entry->fields[ca_expression]) > 0
-                           ? entry->fields[ca_expression]
-                           : NULL);
-    *curr_rule = new_rule;
-    curr_rule = &new_rule->next;
-  }
-  return table;
-}
-
-
-
-static void
-dump_cache_rule(cache_rules* rule,
-               int indent)
-{
-  dumpf(indent, "((cache_rules*)0x%x\n", rule);
-  dumpf(indent, " (valid %d)\n", rule->valid);
-  dumpf(indent, " (old_name \"%s\")\n", rule->old_name);
-  dumpf(indent, " (new_name \"%s\")\n", rule->new_name);
-  dumpf(indent, " (type \"%s\")\n", rule->type);
-  dumpf(indent, " (expression \"%s\")\n", rule->expression);
-  dumpf(indent, " (next 0x%x)\n", rule->next);
-  dumpf(indent, " )\n");
-}
-
-
-static void
-dump_cache_rules(cache_rules* rule, int indent)
-{
-  while (rule) {
-    dump_cache_rule(rule, indent);
-    rule = rule->next;
-  }
-}
-
-
-/****************************************************************/
-
-
-typedef struct _opcode_rules opcode_rules;
-struct _opcode_rules {
-  int first;
-  int last;
-  int force_first;
-  int force_last;
-  int force_slash;
-  char *force_expansion;
-  int use_switch;
-  unsigned special_mask;
-  unsigned special_value;
-  unsigned special_rule;
-  opcode_rules *next;
-};
-static opcode_rules *opcode_table;
-
-
-enum {
-  op_first,
-  op_last,
-  op_force_first,
-  op_force_last,
-  op_force_slash,
-  op_force_expansion,
-  op_use_switch,
-  op_special_mask,
-  op_special_value,
-  op_special_rule,
-  nr_opcode_fields,
-};
-
-
-static opcode_rules *
-load_opcode_rules(char *file_name)
-{
-  table *file = table_open(file_name, nr_opcode_fields, 0);
-  table_entry *entry;
-  opcode_rules *table = NULL;
-  opcode_rules **curr_rule = &table;
-  while ((entry = table_entry_read(file)) != NULL) {
-    opcode_rules *new_rule = ZALLOC(opcode_rules);
-    new_rule->first = target_a2i(hi_bit_nr, entry->fields[op_first]);
-    new_rule->last = target_a2i(hi_bit_nr, entry->fields[op_last]);
-    new_rule->force_first = target_a2i(hi_bit_nr, entry->fields[op_force_first]);
-    new_rule->force_last = target_a2i(hi_bit_nr, entry->fields[op_force_last]);
-    new_rule->force_slash = a2i(entry->fields[op_force_slash]);
-    new_rule->force_expansion = entry->fields[op_force_expansion];
-    new_rule->use_switch = a2i(entry->fields[op_use_switch]);
-    new_rule->special_mask = a2i(entry->fields[op_special_mask]);
-    new_rule->special_value = a2i(entry->fields[op_special_value]);
-    new_rule->special_rule = a2i(entry->fields[op_special_rule]);
-    *curr_rule = new_rule;
-    curr_rule = &new_rule->next;
-  }
-  return table;
-}
-
-  
-static void
-dump_opcode_rule(opcode_rules *rule,
-                int indent)
-{
-  dumpf(indent, "((opcode_rules*)%p\n", rule);
-  if (rule) {
-    dumpf(indent, " (first %d)\n", rule->first);
-    dumpf(indent, " (last %d)\n", rule->last);
-    dumpf(indent, " (force_first %d)\n", rule->force_first);
-    dumpf(indent, " (force_last %d)\n", rule->force_last);
-    dumpf(indent, " (force_slash %d)\n", rule->force_slash);
-    dumpf(indent, " (force_expansion \"%s\")\n", rule->force_expansion);
-    dumpf(indent, " (use_switch %d)\n", rule->use_switch);
-    dumpf(indent, " (special_mask 0x%x)\n", rule->special_mask);
-    dumpf(indent, " (special_value 0x%x)\n", rule->special_value);
-    dumpf(indent, " (special_rule 0x%x)\n", rule->special_rule);
-    dumpf(indent, " (next 0x%x)\n", rule->next);
-  }
-  dumpf(indent, " )\n");
-}
-
-
-static void
-dump_opcode_rules(opcode_rules *rule,
-                 int indent)
-{
-  while (rule) {
-    dump_opcode_rule(rule, indent);
-    rule = rule->next;
-  }
-}
-
-
-/****************************************************************/
-
-typedef struct _insn_field insn_field;
-struct _insn_field {
-  int first;
-  int last;
-  int width;
-  int is_int;
-  int is_slash;
-  int is_string;
-  int val_int;
-  char *pos_string;
-  char *val_string;
-  insn_field *next;
-  insn_field *prev;
-};
-
-typedef struct _insn_fields insn_fields;
-struct _insn_fields {
-  insn_field *bits[max_insn_size];
-  insn_field *first;
-  insn_field *last;
-  unsigned value;
-};
-
-static insn_fields *
-parse_insn_format(table_entry *entry,
-                 char *format)
-{
-  char *chp;
-  insn_fields *fields = ZALLOC(insn_fields);
-
-  /* create a leading sentinal */
-  fields->first = ZALLOC(insn_field);
-  fields->first->first = -1;
-  fields->first->last = -1;
-  fields->first->width = 0;
-
-  /* and a trailing sentinal */
-  fields->last = ZALLOC(insn_field);
-  fields->last->first = insn_size;
-  fields->last->last = insn_size;
-  fields->last->width = 0;
-
-  /* link them together */
-  fields->first->next = fields->last;
-  fields->last->prev = fields->first;
-
-  /* now work through the formats */
-  chp = format;
-
-  while (*chp != '\0') {
-    char *start_pos;
-    char *start_val;
-    int strlen_val;
-    int strlen_pos;
-    insn_field *new_field;
-
-    /* sanity check */
-    if (!isdigit(*chp)) {
-      error("%s:%d: missing position field at `%s'\n",
-           entry->file_name, entry->line_nr, chp);
-    }
-
-    /* break out the bit position */
-    start_pos = chp;
-    while (isdigit(*chp))
-      chp++;
-    strlen_pos = chp - start_pos;
-    if (*chp == '.' && strlen_pos > 0)
-      chp++;
-    else {
-      error("%s:%d: missing field value at %s\n",
-           entry->file_name, entry->line_nr, chp);
-      break;
-    }
-
-    /* break out the value */
-    start_val = chp;
-    while ((*start_val == '/' && *chp == '/')
-          || (isdigit(*start_val) && isdigit(*chp))
-          || (isalpha(*start_val) && (isalnum(*chp) || *chp == '_')))
-      chp++;
-    strlen_val = chp - start_val;
-    if (*chp == ',')
-      chp++;
-    else if (*chp != '\0' || strlen_val == 0) {
-      error("%s:%d: missing field terminator at %s\n",
-           entry->file_name, entry->line_nr, chp);
-      break;
-    }
-
-    /* create a new field and insert it */
-    new_field = ZALLOC(insn_field);
-    new_field->next = fields->last;
-    new_field->prev = fields->last->prev;
-    new_field->next->prev = new_field;
-    new_field->prev->next = new_field;
-
-    /* the value */
-    new_field->val_string = (char*)zalloc(strlen_val+1);
-    strncpy(new_field->val_string, start_val, strlen_val);
-    if (isdigit(*new_field->val_string)) {
-      new_field->val_int = a2i(new_field->val_string);
-      new_field->is_int = 1;
-    }
-    else if (new_field->val_string[0] == '/') {
-      new_field->is_slash = 1;
-    }
-    else {
-      new_field->is_string = 1;
-    }
-    
-    /* the pos */
-    new_field->pos_string = (char*)zalloc(strlen_pos+1);
-    strncpy(new_field->pos_string, start_pos, strlen_pos);
-    new_field->first = target_a2i(hi_bit_nr, new_field->pos_string);
-    new_field->last = new_field->next->first - 1; /* guess */
-    new_field->width = new_field->last - new_field->first + 1; /* guess */
-    new_field->prev->last = new_field->first-1; /*fix*/
-    new_field->prev->width = new_field->first - new_field->prev->first; /*fix*/
-  }
-
-  /* fiddle first/last so that the sentinals `disapear' */
-  ASSERT(fields->first->last < 0);
-  ASSERT(fields->last->first >= insn_size);
-  fields->first = fields->first->next;
-  fields->last = fields->last->prev;
-
-  /* now go over this again, pointing each bit position at a field
-     record */
-  {
-    int i;
-    insn_field *field;
-    field = fields->first;
-    for (i = 0; i < insn_size; i++) {
-      while (field->last < i)
-       field = field->next;
-      fields->bits[i] = field;
-    }
-  }
-
-  /* go over each of the fields, and compute a `value' for the insn */
-  {
-    insn_field *field;
-    fields->value = 0;
-    for (field = fields->first;
-        field->last < insn_size;
-        field = field->next) {
-      fields->value <<= field->width;
-      if (field->is_int)
-       fields->value |= field->val_int;
-    }
-  }
-  return fields;
-}
-
-
-typedef enum {
-  field_constant_int = 1,
-  field_constant_slash = 2,
-  field_constant_string = 3
-} constant_field_types;
-
-
-static int
-insn_field_is_constant(insn_field *field,
-                      opcode_rules *rule)
-{
-  /* field is an integer */
-  if (field->is_int)
-    return field_constant_int;
-  /* field is `/' and treating that as a constant */
-  if (field->is_slash && rule->force_slash)
-    return field_constant_slash;
-  /* field, though variable is on the list */
-  if (field->is_string && rule->force_expansion != NULL) {
-    char *forced_fields = rule->force_expansion;
-    while (*forced_fields != '\0') {
-      int field_len;
-      char *end = strchr(forced_fields, ',');
-      if (end == NULL)
-       field_len = strlen(forced_fields);
-      else
-       field_len = end-forced_fields;
-      if (strncmp(forced_fields, field->val_string, field_len) == 0
-         && field->val_string[field_len] == '\0')
-       return field_constant_string;
-      forced_fields += field_len;
-      if (*forced_fields == ',')
-       forced_fields++;
-    }
-  }
-  return 0;
-}
-
-
-static void
-dump_insn_field(insn_field *field,
-               int indent)
-{
-
-  printf("(insn_field*)0x%x\n", (unsigned)field);
-
-  dumpf(indent, "(first %d)\n", field->first);
-
-  dumpf(indent, "(last %d)\n", field->last);
-
-  dumpf(indent, "(width %d)\n", field->width);
-
-  if (field->is_int)
-    dumpf(indent, "(is_int %d)\n", field->val_int);
-
-  if (field->is_slash)
-    dumpf(indent, "(is_slash)\n");
-
-  if (field->is_string)
-    dumpf(indent, "(is_string `%s')\n", field->val_string);
-  
-  dumpf(indent, "(next 0x%x)\n", field->next);
-  
-  dumpf(indent, "(prev 0x%x)\n", field->prev);
-  
+#include "build-config.h"
 
-}
-
-static void
-dump_insn_fields(insn_fields *fields,
-                int indent)
-{
-  int i;
-
-  printf("(insn_fields*)%p\n", fields);
-
-  dumpf(indent, "(first 0x%x)\n", fields->first);
-  dumpf(indent, "(last 0x%x)\n", fields->last);
-
-  dumpf(indent, "(value 0x%x)\n", fields->value);
-
-  for (i = 0; i < insn_size; i++) {
-    dumpf(indent, "(bits[%d] ", i, fields->bits[i]);
-    dump_insn_field(fields->bits[i], indent+1);
-    dumpf(indent, " )\n");
-  }
-
-}
-
-
-/****************************************************************/
-
-typedef struct _opcode_field opcode_field;
-struct _opcode_field {
-  int first;
-  int last;
-  int is_boolean;
-  opcode_field *parent;
-};
-
-static opcode_field *
-opcode_field_new(void)
-{
-  opcode_field *new_field = (opcode_field*)zalloc(sizeof(opcode_field));
-  ASSERT(new_field != NULL);
-  new_field->first = insn_size;
-  new_field->last = -1;
-  return new_field;
-}
-
-static void
-dump_opcode_field(opcode_field *field, int indent, int levels)
-{
-  printf("(opcode_field*)%p\n", field);
-  if (levels && field != NULL) {
-    dumpf(indent, "(first %d)\n", field->first);
-    dumpf(indent, "(last %d)\n", field->last);
-    dumpf(indent, "(is_boolean %d)\n", field->is_boolean);
-    dumpf(indent, "(parent ");
-    dump_opcode_field(field->parent, indent, levels-1);
-  }
-}
-
-
-/****************************************************************/
-
-typedef struct _insn_bits insn_bits;
-struct _insn_bits {
-  int is_expanded;
-  int value;
-  insn_field *field;
-  opcode_field *opcode;
-  insn_bits *last;
-};
-
-
-static void
-dump_insn_bits(insn_bits *bits, int indent, int levels)
-{
-  printf("(insn_bits*)%p\n", bits);
-
-  if (levels && bits != NULL) {
-    dumpf(indent, "(value %d)\n", bits->value);
-    dumpf(indent, "(opcode ");
-    dump_opcode_field(bits->opcode, indent+1, 0);
-    dumpf(indent, " )\n");
-    dumpf(indent, "(field ");
-    dump_insn_field(bits->field, indent+1);
-    dumpf(indent, " )\n");
-    dumpf(indent, "(last ");
-    dump_insn_bits(bits->last, indent+1, levels-1);
-  }
-}
-
-
-/****************************************************************/
-
-
-typedef enum {
-  insn_format,
-  insn_form,
-  insn_flags,
-  insn_nmemonic,
-  insn_name,
-  insn_comment,
-  nr_insn_table_fields
-} insn_table_fields;
-
-typedef enum {
-  function_type = insn_format,
-  function_name = insn_name,
-  function_param = insn_comment
-} function_table_fields;
-
-typedef enum {
-  model_name = insn_name,
-  model_func = insn_comment,
-} model_table_fields;
-
-typedef struct _insn insn;
-struct _insn {
-  table_entry *file_entry;
-  insn_fields *fields;
-  insn *next;
-};
-
-typedef struct _model_func_unit model_func_unit;
-struct _model_func_unit {
-  model_func_unit *next;
-  char *name;
-  char *comment;
-  int number;
-  unsigned mask;
-};
-
-typedef struct _model model;
-struct _model {
-  model *next;
-  char *name;
-  model_func_unit *func_unit_start;
-  model_func_unit *func_unit_end;
-};
-  
-typedef struct _insn_table insn_table;
-struct _insn_table {
-  int opcode_nr;
-  insn_bits *expanded_bits;
-  int nr_insn;
-  insn *insns;
-  insn *functions;
-  insn *last_function;
-  int max_func_unit_name_len;
-  unsigned max_func_unit_mask;
-  opcode_rules *opcode_rule;
-  opcode_field *opcode;
-  int nr_entries;
-  insn_table *entries;
-  insn_table *sibling;
-  insn_table *parent;
-};
-
-typedef enum {
-  insn_model_name,
-  insn_model_unit,
-  insn_model_issue,
-  insn_model_done,
-  insn_model_flags,
-  nr_insn_model_table_fields
-} insn_model_table_fields;
-
-static model *models;
-static model *last_model;
-
-
-static void
-insn_table_insert_function(insn_table *table,
-                          table_entry *file_entry)
-{
-  /* create a new function */
-  insn *new_function = ZALLOC(insn);
-  new_function->file_entry = file_entry;
-
-  /* append it to the end of the function list */
-  if (table->last_function)
-    table->last_function->next = new_function;
-  else
-    table->functions = new_function;
-  table->last_function = new_function;
-}
-
-
-static void
-model_table_insert(insn_table *table,
-                  table_entry *file_entry)
-{
-  /* create a new model */
-  model *new_model = ZALLOC(model);
-  model_func_unit *func_unit;
-  char *ptr, *end, *end_name, *comment, *name;
-  int ch;
-  int name_len;
-  int func_name_len;
-  unsigned unit, mask;
-  int number;
-
-  new_model->name = file_entry->fields[model_name];
-  name_len = strlen(new_model->name);
-
-  /* append it to the end of the model list */
-  if (last_model)
-    last_model->next = new_model;
-  else
-    models = new_model;
-  last_model = new_model;
-
-  /* Parse the function units separated by commas */
-  unit = 1;
-  for (ptr = file_entry->fields[model_func];
-       ((ch = *ptr) != '\0') && (ch != '\n');
-       ptr = (*end == ',') ? end+1 : end) {
-
-    while (ch == ' ' || ch == '\t')
-      ch = *++ptr;
-
-    if (!ch || ch == '\n')
-      break;
-
-    /* Search for comma or newline ending field */
-    end = ptr;
-    end_name = (char *)0;
-
-    if (ch == ',')
-      continue;
-
-    while (ch != '\0' && ch != ',' && ch != '\n') {
-      if (end_name == (char *)0 && (ch == '=' || isspace(ch)))
-       end_name = end;
-
-      ch = *++end;
-    }
-    if (!end_name)
-      end_name = end;
-
-    func_unit = ZALLOC(model_func_unit);
-    if (new_model->func_unit_end)
-      new_model->func_unit_end->next = func_unit;
-    else
-      new_model->func_unit_start = func_unit;
-
-    new_model->func_unit_end = func_unit;
-
-    /* Record function unit name as model name _ unit name */
-    func_name_len = name_len + end_name - ptr + 2;
-    if (table->max_func_unit_name_len < func_name_len)
-      table->max_func_unit_name_len = func_name_len;
-
-    func_unit->name = name = (char *)zalloc(func_name_len);
-    memcpy(name, new_model->name, name_len);
-    name[name_len] = '_';
-    memcpy(name + name_len + 1, ptr, end_name - ptr);
-
-    /* See if there are multiple functional units */
-    if (*end_name == '=') {
-      number = 0;
-      for(end_name++; end_name < end && isdigit(*end_name); end_name++)
-       number = number * 10 + (*end_name - '0');
-    } else {
-      number = 1;
-    }
-
-    /* Now figure out the mask for these unit(s) */
-    func_unit->number = number;
-    mask = 0;
-    while (number--) {
-      ASSERT(unit != 0);
-      mask |= unit;
-      unit <<= 1;
-    }
-    func_unit->mask = mask;
-    table->max_func_unit_mask |= mask;
-
-    /* Now figure out comments */
-    for (comment = end_name; comment < end && ((ch = *comment) == ' ' || ch == '\t'); comment++)
-      ;
-
-    if (comment < end) {
-      func_unit->comment = (char *)zalloc(end - comment + 1);
-      memcpy(func_unit->comment, comment, end - comment);
-    }
-  }
-}
-
-
-static void
-insn_table_insert_insn(insn_table *table,
-                      table_entry *file_entry,
-                      insn_fields *fields)
-{
-  insn **ptr_to_cur_insn = &table->insns;
-  insn *cur_insn = *ptr_to_cur_insn;
-  table_model_entry *insn_model_ptr;
-  model *model_ptr;
-
-  /* create a new instruction */
-  insn *new_insn = ZALLOC(insn);
-  new_insn->file_entry = file_entry;
-  new_insn->fields = fields;
-
-  /* Check out any model information returned to make sure the model
-     is correct.  */
-  for(insn_model_ptr = file_entry->model_first; insn_model_ptr; insn_model_ptr = insn_model_ptr->next) {
-    char *name = insn_model_ptr->fields[insn_model_name];
-
-    for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
-      if (strcmp(name, model_ptr->name) == 0) {
-
-       /* Replace the name field with that of the global model, so that when we
-          want to print it out, we can just compare pointers.  */
-       insn_model_ptr->fields[insn_model_name] = model_ptr->name;
-       break;
-      }
-    }
-
-    if (!model_ptr)
-      error("%s:%d: machine model `%s' was not known about\n",
-           file_entry->file_name, file_entry->line_nr, name);
-  }
-
-  /* insert it according to the order of the fields */
-  while (cur_insn != NULL
-        && new_insn->fields->value >= cur_insn->fields->value) {
-    ptr_to_cur_insn = &cur_insn->next;
-    cur_insn = *ptr_to_cur_insn;
-  }
-
-  new_insn->next = cur_insn;
-  *ptr_to_cur_insn = new_insn;
-
-  table->nr_insn++;
-}
-
-
-static opcode_field *
-insn_table_find_opcode_field(insn *insns,
-                            opcode_rules *rule,
-                            int string_only)
-{
-  opcode_field *curr_opcode = opcode_field_new();
-  insn *entry;
-
-  ASSERT(rule);
-
-  for (entry = insns; entry != NULL; entry = entry->next) {
-    insn_fields *fields = entry->fields;
-    opcode_field new_opcode;
-
-    /* find a start point for the opcode field */
-    new_opcode.first = rule->first;
-    while (new_opcode.first <= rule->last
-          && (!string_only
-              || insn_field_is_constant(fields->bits[new_opcode.first],
-                                        rule) != field_constant_string)
-          && (string_only
-              || !insn_field_is_constant(fields->bits[new_opcode.first],
-                                         rule)))
-      new_opcode.first = fields->bits[new_opcode.first]->last + 1;
-    ASSERT(new_opcode.first > rule->last
-          || (string_only
-              && insn_field_is_constant(fields->bits[new_opcode.first],
-                                        rule) == field_constant_string)
-          || (!string_only
-              && insn_field_is_constant(fields->bits[new_opcode.first],
-                                        rule)));
-  
-    /* find the end point for the opcode field */
-    new_opcode.last = rule->last;
-    while (new_opcode.last >= rule->first
-          && (!string_only
-              || insn_field_is_constant(fields->bits[new_opcode.last],
-                                        rule) != field_constant_string)
-          && (string_only
-              || !insn_field_is_constant(fields->bits[new_opcode.last],
-                                         rule)))
-      new_opcode.last = fields->bits[new_opcode.last]->first - 1;
-    ASSERT(new_opcode.last < rule->first
-          || (string_only
-              && insn_field_is_constant(fields->bits[new_opcode.last],
-                                        rule) == field_constant_string)
-          || (!string_only
-              && insn_field_is_constant(fields->bits[new_opcode.last],
-                                        rule)));
-
-    /* now see if our current opcode needs expanding */
-    if (new_opcode.first <= rule->last
-       && curr_opcode->first > new_opcode.first)
-      curr_opcode->first = new_opcode.first;
-    if (new_opcode.last >= rule->first
-       && curr_opcode->last < new_opcode.last)
-      curr_opcode->last = new_opcode.last;
-    
-  }
-
-  /* was any thing interesting found? */
-  if (curr_opcode->first > rule->last) {
-    ASSERT(curr_opcode->last < rule->first);
-    return NULL;
-  }
-  ASSERT(curr_opcode->last >= rule->first);
-  ASSERT(curr_opcode->first <= rule->last);
-
-  /* if something was found, check it includes the forced field range */
-  if (!string_only
-      && curr_opcode->first > rule->force_first) {
-    curr_opcode->first = rule->force_first;
-  }
-  if (!string_only
-      && curr_opcode->last < rule->force_last) {
-    curr_opcode->last = rule->force_last;
-  }
-  /* handle special case elminating any need to do shift after mask */
-  if (string_only
-      && rule->force_last == insn_size-1) {
-    curr_opcode->last = insn_size-1;
-  }
-
-  /* handle any special cases */
-  switch (rule->special_rule) {
-  case 0: /* let the above apply */
-    break;
-  case 1: /* expand a limited nr of bits, ignoring the rest */
-    curr_opcode->first = rule->force_first;
-    curr_opcode->last = rule->force_last;
-    break;
-  case 2: /* boolean field */
-    curr_opcode->is_boolean = 1;
-    break;
-  }
-
-  return curr_opcode;
-}
-
-
-static void
-insn_table_insert_expanded(insn_table *table,
-                          insn *old_insn,
-                          int new_opcode_nr,
-                          insn_bits *new_bits)
-{
-  insn_table **ptr_to_cur_entry = &table->entries;
-  insn_table *cur_entry = *ptr_to_cur_entry;
-
-  /* find the new table for this entry */
-  while (cur_entry != NULL
-        && cur_entry->opcode_nr < new_opcode_nr) {
-    ptr_to_cur_entry = &cur_entry->sibling;
-    cur_entry = *ptr_to_cur_entry;
-  }
+#include "filter.h"
 
-  if (cur_entry == NULL || cur_entry->opcode_nr != new_opcode_nr) {
-    insn_table *new_entry = ZALLOC(insn_table);
-    new_entry->opcode_nr = new_opcode_nr;
-    new_entry->expanded_bits = new_bits;
-    new_entry->opcode_rule = table->opcode_rule->next;
-    new_entry->sibling = cur_entry;
-    new_entry->parent = table;
-    *ptr_to_cur_entry = new_entry;
-    cur_entry = new_entry;
-    table->nr_entries++;
-  }
-  /* ASSERT new_bits == cur_entry bits */
-  ASSERT(cur_entry != NULL && cur_entry->opcode_nr == new_opcode_nr);
-  insn_table_insert_insn(cur_entry,
-                        old_insn->file_entry,
-                        old_insn->fields);
-}
-
-static void
-insn_table_expand_opcode(insn_table *table,
-                        insn *instruction,
-                        int field_nr,
-                        int opcode_nr,
-                        insn_bits *bits)
-{
-
-  if (field_nr > table->opcode->last) {
-    insn_table_insert_expanded(table, instruction, opcode_nr, bits);
-  }
-  else {
-    insn_field *field = instruction->fields->bits[field_nr];
-    if (field->is_int || field->is_slash) {
-      ASSERT(field->first >= table->opcode->first
-            && field->last <= table->opcode->last);
-      insn_table_expand_opcode(table, instruction, field->last+1,
-                              ((opcode_nr << field->width) + field->val_int),
-                              bits);
-    }
-    else {
-      int val;
-      int last_pos = ((field->last < table->opcode->last)
-                       ? field->last : table->opcode->last);
-      int first_pos = ((field->first > table->opcode->first)
-                        ? field->first : table->opcode->first);
-      int width = last_pos - first_pos + 1;
-      int last_val = (table->opcode->is_boolean
-                     ? 2 : (1 << width));
-      for (val = 0; val < last_val; val++) {
-       insn_bits *new_bits = ZALLOC(insn_bits);
-       new_bits->field = field;
-       new_bits->value = val;
-       new_bits->last = bits;
-       new_bits->opcode = table->opcode;
-       insn_table_expand_opcode(table, instruction, last_pos+1,
-                                ((opcode_nr << width) | val),
-                                new_bits);
-      }
-    }
-  }
-}
-
-static void
-insn_table_insert_expanding(insn_table *table,
-                           insn *entry)
-{
-  insn_table_expand_opcode(table,
-                          entry,
-                          table->opcode->first,
-                          0,
-                          table->expanded_bits);
-}
-
-
-static void
-insn_table_expand_insns(insn_table *table)
-{
-
-  ASSERT(table->nr_insn >= 1);
-
-  /* determine a valid opcode */
-  while (table->opcode_rule) {
-    /* specials only for single instructions */
-    if ((table->nr_insn > 1
-        && table->opcode_rule->special_mask == 0
-        && table->opcode_rule->special_rule == 0)
-       || (table->nr_insn == 1
-           && table->opcode_rule->special_mask != 0
-           && ((table->insns->fields->value
-                & table->opcode_rule->special_mask)
-               == table->opcode_rule->special_value))
-       || (idecode_expand_semantics
-           && table->opcode_rule->special_mask == 0
-           && table->opcode_rule->special_rule == 0))
-      table->opcode =
-       insn_table_find_opcode_field(table->insns,
-                                    table->opcode_rule,
-                                    table->nr_insn == 1/*string*/
-                                    );
-    if (table->opcode != NULL)
-      break;
-    table->opcode_rule = table->opcode_rule->next;
-  }
-
-  /* did we find anything */
-  if (table->opcode == NULL) {
-    return;
-  }
-  ASSERT(table->opcode != NULL);
-
-  /* back link what we found to its parent */
-  if (table->parent != NULL) {
-    ASSERT(table->parent->opcode != NULL);
-    table->opcode->parent = table->parent->opcode;
-  }
-
-  /* expand the raw instructions according to the opcode */
-  {
-    insn *entry;
-    for (entry = table->insns; entry != NULL; entry = entry->next) {
-      insn_table_insert_expanding(table, entry);
-    }
-  }
-
-  /* and do the same for the sub entries */
-  {
-    insn_table *entry;
-    for (entry = table->entries; entry != NULL; entry =  entry->sibling) {
-      insn_table_expand_insns(entry);
-    }
-  }
-}
-
-
-
-static insn_table *
-insn_table_load_insns(char *file_name)
-{
-  table *file = table_open(file_name, nr_insn_table_fields, nr_insn_model_table_fields);
-  insn_table *table = ZALLOC(insn_table);
-  table_entry *file_entry;
-  table->opcode_rule = opcode_table;
-
-  while ((file_entry = table_entry_read(file)) != NULL) {
-    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 if (it_is("model", file_entry->fields[insn_flags])) {
-      model_table_insert(table, file_entry);
-    }
-    else {
-      insn_fields *fields;
-      /* skip instructions that aren't relevant to the mode */
-      filter *filt = filters;
-      while (filt != NULL) {
-       if (it_is(filt->flag, file_entry->fields[insn_flags]))
-         break;
-       filt = filt->next;
-      }
-      if (filt == NULL) {
-       /* create/insert the new instruction */
-       fields = parse_insn_format(file_entry,
-                                  file_entry->fields[insn_format]);
-       insn_table_insert_insn(table, file_entry, fields);
-      }
-    }
-  }
-  return table;
-}
-
-
-static void
-dump_insn(insn *entry, int indent, int levels)
-{
-  printf("(insn*)%p\n", entry);
-
-  if (levels && entry != NULL) {
-
-    dumpf(indent, "(file_entry ");
-    dump_table_entry(entry->file_entry, indent+1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(fields ");
-    dump_insn_fields(entry->fields, indent+1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(next ");
-    dump_insn(entry->next, indent+1, levels-1);
-    dumpf(indent, " )\n");
-
-  }
-
-}
-
-
-static void
-dump_insn_table(insn_table *table,
-               int indent, int levels)
-{
-
-  printf("(insn_table*)%p\n", table);
-
-  if (levels && table != NULL) {
-
-    dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr);
-
-    dumpf(indent, "(expanded_bits ");
-    dump_insn_bits(table->expanded_bits, indent+1, -1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(int nr_insn %d)\n", table->nr_insn);
-
-    dumpf(indent, "(insns ");
-    dump_insn(table->insns, indent+1, table->nr_insn);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(opcode_rule ");
-    dump_opcode_rule(table->opcode_rule, indent+1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(opcode ");
-    dump_opcode_field(table->opcode, indent+1, 1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(nr_entries %d)\n", table->entries);
-    dumpf(indent, "(entries ");
-    dump_insn_table(table->entries, indent+1, table->nr_entries);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(sibling ", table->sibling);
-    dump_insn_table(table->sibling, indent+1, levels-1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(parent ", table->parent);
-    dump_insn_table(table->parent, indent+1, 0);
-    dumpf(indent, " )\n");
-
-  }
-}
-
-
-/****************************************************************/
-
-
-static void
-lf_print_insn_bits(lf *file, insn_bits *bits)
-{
-  if (bits == NULL)
-    return;
-  lf_print_insn_bits(file, bits->last);
-  lf_putchr(file, '_');
-  lf_putstr(file, bits->field->val_string);
-  if (!bits->opcode->is_boolean || bits->value == 0) {
-    if (bits->opcode->last < bits->field->last)
-      lf_putint(file, bits->value << (bits->field->last - bits->opcode->last));
-    else
-      lf_putint(file, bits->value);
-  }
-}
-
-static void
-lf_print_opcodes(lf *file,
-                insn_table *table)
-{
-  if (table != NULL) {
-    while (1) {
-      lf_printf(file, "_%d_%d",
-               table->opcode->first,
-               table->opcode->last);
-      if (table->parent == NULL) break;
-      lf_printf(file, "__%d", table->opcode_nr);
-      table = table->parent;
-    }
-  }
-}
-
-static void
-lf_print_table_name(lf *file,
-                   insn_table *table)
-{
-  lf_printf(file, "idecode_table");
-  lf_print_opcodes(file, table);
-}
-
-
-
-typedef enum {
-  function_name_prefix_semantics,
-  function_name_prefix_idecode,
-  function_name_prefix_itable,
-  function_name_prefix_none
-} lf_function_name_prefixes;
-
-static void
-lf_print_function_name(lf *file,
-                      char *basename,
-                      insn_bits *expanded_bits,
-                      lf_function_name_prefixes prefix)
-{
-
-  /* the prefix */
-  switch (prefix) {
-  case function_name_prefix_semantics:
-    lf_putstr(file, "semantic_");
-    break;
-  case function_name_prefix_idecode:
-    lf_printf(file, "idecode_");
-    break;
-  case function_name_prefix_itable:
-    lf_putstr(file, "itable_");
-    break;
-  default:
-    break;
-  }
-
-  /* the function name */
-  {
-    char *pos;
-    for (pos = basename;
-        *pos != '\0';
-        pos++) {
-      switch (*pos) {
-      case '/':
-      case '-':
-       break;
-      case ' ':
-       lf_putchr(file, '_');
-       break;
-      default:
-       lf_putchr(file, *pos);
-       break;
-      }
-    }
-  }
-
-  /* the suffix */
-  if (idecode_expand_semantics)
-    lf_print_insn_bits(file, expanded_bits);
-}
-
-
-static void
-lf_print_idecode_table(lf *file,
-                      insn_table *entry)
-{
-  int can_assume_leaf;
-  opcode_rules *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 = opcode_table;
-  while (opcode_rule != NULL
-        && opcode_rule->use_switch)
-    opcode_rule = opcode_rule->next;
-  while (opcode_rule != NULL
-        && opcode_rule->use_switch
-        && opcode_rule->special_rule)
-    opcode_rule = opcode_rule->next;
-  can_assume_leaf = opcode_rule == NULL;
-
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-  {
-    lf_printf(file, "idecode_table_entry *table = ");
-    lf_print_table_name(file, entry);
-    lf_printf(file, ";\n");
-    lf_printf(file, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
-             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, "while (1) {\n");
-    lf_indent(file, +2);
-    {
-      lf_printf(file, "while (table_entry->mask != 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");
-      if (!idecode_cache && can_assume_leaf) {
-       lf_printf(file, "return (((idecode_semantic*)\n");
-       lf_printf(file, "         table_entry->function_or_table)\n");
-       lf_printf(file, "        (%s));\n", semantic_actual);
-      }
-      else if (!idecode_cache && !can_assume_leaf) {
-       lf_printf(file, "if (table_entry->shift == 0)");
-       lf_printf(file, "  return (((idecode_semantic*)\n");
-       lf_printf(file, "           table_entry->function_or_table)\n");
-       lf_printf(file, "          (%s));\n", semantic_actual);
-      }
-      else {
-       lf_printf(file, "if (table_entry->shift == 0)\n");
-       lf_printf(file, "  return (((idecode_crack*)\n");
-       lf_printf(file, "           table_entry->function_or_table)\n");
-       lf_printf(file, "          (%s));\n", cache_idecode_actual);
-      }
-      if (!can_assume_leaf) {
-       lf_printf(file, "opcode = (instruction & table_entry->shift) != 0;\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");
-  }
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-}
-
-
-static void
-lf_print_my_prefix(lf *file,
-                  table_entry *file_entry,
-                  int idecode)
-{
-  lf_printf(file, "const char *const my_prefix = \n");
-  lf_printf(file, "  \"%s:%s:%s:%d\";\n",
-           filter_filename (file_entry->file_name),
-           (idecode ? "idecode" : "semantics"),
-           file_entry->fields[insn_name],
-           file_entry->line_nr);
-}
-
-
-static void
-lf_print_ptrace(lf *file,
-               int idecode)
-{
-  lf_printf(file, "\n");
-  lf_printf(file, "ITRACE(trace_%s, (\"\\n\"));\n",
-           (idecode ? "idecode" : "semantics"));
-}
-
-
-/****************************************************************/
-
-typedef void leaf_handler
-(insn_table *entry,
- void *data,
- int depth);
-typedef void padding_handler
-(insn_table *table,
- void *data,
- int depth,
- int opcode_nr);
-
-
-static void
-insn_table_traverse_tree(insn_table *table,
-                        void *data,
-                        int depth,
-                        leaf_handler *start,
-                        leaf_handler *leaf,
-                        leaf_handler *end,
-                        padding_handler *padding)
-{
-  insn_table *entry;
-  int entry_nr;
-  
-  ASSERT(table != NULL
-        && table->opcode != NULL
-        && table->nr_entries > 0
-        && table->entries != 0);
-
-  if (start != NULL && depth >= 0)
-    start(table, data, depth);
-
-  for (entry_nr = 0, entry = table->entries;
-       entry_nr < (table->opcode->is_boolean
-                  ? 2
-                  : (1 << (table->opcode->last - table->opcode->first + 1)));
-       entry_nr ++) {
-    if (entry == NULL
-       || (!table->opcode->is_boolean
-           && entry_nr < entry->opcode_nr)) {
-      if (padding != NULL && depth >= 0)
-       padding(table, data, depth, entry_nr);
-    }
-    else {
-      ASSERT(entry != NULL && (entry->opcode_nr == entry_nr
-                              || table->opcode->is_boolean));
-      if (entry->opcode != NULL && depth != 0) {
-       insn_table_traverse_tree(entry, data, depth+1,
-                                start, leaf, end, padding);
-      }
-      else if (depth >= 0) {
-       if (leaf != NULL)
-         leaf(entry, data, depth);
-      }
-      entry = entry->sibling;
-    }
-  }
-  if (end != NULL && depth >= 0)
-    end(table, data, depth);
-}
-
-
-typedef void function_handler
-(insn_table *table,
- void *data,
- table_entry *function);
-
-static void
-insn_table_traverse_function(insn_table *table,
-                            void *data,
-                            function_handler *leaf)
-{
-  insn *function;
-  for (function = table->functions;
-       function != NULL;
-       function = function->next) {
-    leaf(table, data, function->file_entry);
-  }
-}
-
-
-typedef void insn_handler
-(insn_table *table,
- void *data,
- insn *instruction);
-
-static void
-insn_table_traverse_insn(insn_table *table,
-                        void *data,
-                        insn_handler *leaf)
-{
-  insn *instruction;
-  for (instruction = table->insns;
-       instruction != NULL;
-       instruction = instruction->next) {
-    leaf(table, data, instruction);
-  }
-}
-
-
-static void
-update_depth(insn_table *entry,
-            void *data,
-            int depth)
-{
-  int *max_depth = (int*)data;
-  if (*max_depth < depth)
-    *max_depth = depth;
-}
-
-
-static int
-insn_table_depth(insn_table *table)
-{
-  int depth = 0;
-  insn_table_traverse_tree(table,
-                          &depth,
-                          1,
-                          NULL, /*start*/
-                          update_depth,
-                          NULL, /*end*/
-                          NULL); /*padding*/
-  return depth;
-}
-
-
-/****************************************************************/
-
-static void
-dump_traverse_start(insn_table *table,
-                   void *data,
-                   int depth)
-{
-  dumpf(depth*2, "(%d\n", table->opcode_nr);
-}
-
-static void
-dump_traverse_leaf(insn_table *entry,
-                  void *data,
-                  int depth)
-{
-  ASSERT(entry->nr_entries == 0
-        && entry->nr_insn == 1
-        && entry->opcode == NULL);
-  dumpf(depth*2, ".%d %s\n", entry->opcode_nr,
-       entry->insns->file_entry->fields[insn_format]);
-}
-
-static void
-dump_traverse_end(insn_table *table,
-                 void *data,
-                 int depth)
-{
-  dumpf(depth*2, ")\n");
-}
-
-static void
-dump_traverse_padding(insn_table *table,
-                     void *data,
-                     int depth,
-                     int opcode_nr)
-{
-  dumpf(depth*2, ".<%d>\n", opcode_nr);
-}
-
-
-static void
-dump_traverse(insn_table *table)
-{
-  insn_table_traverse_tree(table, NULL, 1,
-                          dump_traverse_start,
-                          dump_traverse_leaf,
-                          dump_traverse_end,
-                          dump_traverse_padding);
-}
-
-
-/****************************************************************/
-
-
-static void
-semantics_h_print_function(lf *file,
-                          char *basename,
-                          insn_bits *expanded_bits)
-{
-  lf_printf(file, "\n");
-  lf_printf(file, "INLINE_SEMANTICS unsigned_word ");
-  lf_print_function_name(file,
-                        basename,
-                        expanded_bits,
-                        function_name_prefix_semantics);
-  lf_printf(file, "\n(%s);\n", 
-           (idecode_cache ? cache_semantic_formal : semantic_formal));
-}
-
-
-static void
-semantics_h_leaf(insn_table *entry,
-                void *data,
-                int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->nr_insn == 1);
-  semantics_h_print_function(file,
-                            entry->insns->file_entry->fields[insn_name],
-                            entry->expanded_bits);
-}
-
-static void
-semantics_h_insn(insn_table *entry,
-                void *data,
-                insn *instruction)
-{
-  lf *file = (lf*)data;
-  semantics_h_print_function(file,
-                            instruction->file_entry->fields[insn_name],
-                            NULL);
-}
-
-static void
-semantics_h_function(insn_table *entry,
-                    void *data,
-                    table_entry *function)
-{
-  lf *file = (lf*)data;
-  if (function->fields[function_type] == NULL
-      || function->fields[function_type][0] == '\0') {
-    semantics_h_print_function(file,
-                              function->fields[function_name],
-                              NULL);
-  }
-  else {
-    lf_printf(file, "\n");
-    lf_printf(file, "INLINE_SEMANTICS %s %s\n(%s);\n",
-             function->fields[function_type],
-             function->fields[function_name],
-             function->fields[function_param]);
-  }
-}
-
-
-static void 
-gen_semantics_h(insn_table *table, lf *file)
-{
-
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _SEMANTICS_H_\n");
-  lf_printf(file, "#define _SEMANTICS_H_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef INLINE_SEMANTICS\n");
-  lf_printf(file, "#define INLINE_SEMANTICS\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "\n");
-
-  /* output a declaration for all functions */
-  insn_table_traverse_function(table,
-                              file,
-                              semantics_h_function);
-
-  /* output a declaration for all instructions */
-  if (idecode_expand_semantics)
-    insn_table_traverse_tree(table,
-                            file,
-                            1,
-                            NULL, /* start */
-                            semantics_h_leaf, /* leaf */
-                            NULL, /* end */
-                            NULL); /* padding */
-  else
-    insn_table_traverse_insn(table,
-                            file,
-                            semantics_h_insn);
-
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _SEMANTICS_H_ */\n");
-
-}
-
-/****************************************************************/
-
-typedef struct _icache_tree icache_tree;
-struct _icache_tree {
-  char *name;
-  icache_tree *next;
-  icache_tree *children;
-};
-
-static icache_tree *
-icache_tree_insert(icache_tree *tree,
-                  char *name)
-{
-  icache_tree *new_tree;
-  /* find it */
-  icache_tree **ptr_to_cur_tree = &tree->children;
-  icache_tree *cur_tree = *ptr_to_cur_tree;
-  while (cur_tree != NULL
-        && strcmp(cur_tree->name, name) < 0) {
-    ptr_to_cur_tree = &cur_tree->next;
-    cur_tree = *ptr_to_cur_tree;
-  }
-  ASSERT(cur_tree == NULL
-        || strcmp(cur_tree->name, name) >= 0);
-  /* already in the tree */
-  if (cur_tree != NULL
-      && strcmp(cur_tree->name, name) == 0)
-    return cur_tree;
-  /* missing, insert it */
-  ASSERT(cur_tree == NULL
-        || strcmp(cur_tree->name, name) > 0);
-  new_tree = ZALLOC(icache_tree);
-  new_tree->name = name;
-  new_tree->next = cur_tree;
-  *ptr_to_cur_tree = new_tree;
-  return new_tree;
-}
-
-
-static icache_tree *
-insn_table_cache_fields(insn_table *table)
-{
-  icache_tree *tree = ZALLOC(icache_tree);
-  insn *instruction;
-  for (instruction = table->insns;
-       instruction != NULL;
-       instruction = instruction->next) {
-    insn_field *field;
-    icache_tree *form =
-      icache_tree_insert(tree,
-                        instruction->file_entry->fields[insn_form]);
-    for (field = instruction->fields->first;
-        field != NULL;
-        field = field->next) {
-      if (field->is_string)
-       icache_tree_insert(form, field->val_string);
-    }
-  }
-  return tree;
-}
-
-
-
-static void
-gen_icache_h(icache_tree *tree,
-            lf *file)
-{
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _ICACHE_H_\n");
-  lf_printf(file, "#define _ICACHE_H_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef INLINE_ICACHE\n");
-  lf_printf(file, "#define INLINE_ICACHE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-
-  lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
-           idecode_cache);
-  lf_printf(file, "\n");
-
-  /* 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");
-    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) {
-       cache_rules *cache_rule;
-       int found_rule = 0;
-       for (cache_rule = cache_table;
-            cache_rule != NULL;
-            cache_rule = cache_rule->next) {
-         if (strcmp(field->name, cache_rule->old_name) == 0) {
-           found_rule = 1;
-           if (cache_rule->new_name != NULL)
-             lf_printf(file, "      %s %s; /* %s */\n",
-                       (cache_rule->type == NULL
-                        ? "unsigned" 
-                        : cache_rule->type),
-                       cache_rule->new_name,
-                       cache_rule->old_name);
-         }
-       }
-       if (!found_rule)
-         lf_printf(file, "      unsigned %s;\n", field->name);
-      }
-      lf_printf(file, "    } %s;\n", form->name);
-    }
-    lf_printf(file, "  } crack;\n");
-    lf_printf(file, "} idecode_cache;\n");
-  }
-  else {
-    /* alernativly, since no cache, #define the fields to be
-       extractions from the instruction variable */
-    cache_rules *cache_rule;
-    lf_printf(file, "\n");
-    for (cache_rule = cache_table;
-        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");
-  lf_printf(file, "#endif /* _ICACHE_H_ */\n");
-}
-
-
-
-
-/****************************************************************/
-
-
-static void
-lf_print_c_extraction(lf *file,
-                     insn *instruction,
-                     char *field_name,
-                     char *field_type,
-                     char *field_expression,
-                     insn_field *cur_field,
-                     insn_bits *bits,
-                     int get_value_from_cache,
-                     int put_value_in_cache)
-{
-  ASSERT(field_name != NULL);
-  if (bits != NULL
-      && (!bits->opcode->is_boolean || bits->value == 0)
-      && strcmp(field_name, cur_field->val_string) == 0) {
-    ASSERT(bits->field == cur_field);
-    ASSERT(field_type == NULL);
-    table_entry_lf_c_line_nr(file, instruction->file_entry);
-    lf_printf(file, "const unsigned %s = ",
-             field_name);
-    if (bits->opcode->last < bits->field->last)
-      lf_printf(file, "%d;\n",
-               bits->value << (bits->field->last - bits->opcode->last));
-    else
-      lf_printf(file, "%d;\n", bits->value);
-  }
-  else {
-    /* put the field in the local variable */
-    table_entry_lf_c_line_nr(file, instruction->file_entry);
-    lf_printf(file, "%s const %s = ",
-             field_type == NULL ? "unsigned" : field_type,
-             field_name);
-    /* getting it from the cache */
-    if (get_value_from_cache || put_value_in_cache) {
-      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? */
-       lf_printf(file, " = ");
-    }
-    if (!get_value_from_cache) {
-      if (strcmp(field_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
-       lf_printf(file, "eval_%s", field_name);
-    }
-    lf_printf(file, ";\n");
-  }
-}
-
-
-static void
-lf_print_c_extractions(lf *file,
-                      insn *instruction,
-                      insn_bits *expanded_bits,
-                      int get_value_from_cache,
-                      int put_value_in_cache)
-{
-  insn_field *cur_field;
-
-  /* extract instruction fields */
-  lf_printf(file, "/* extraction: %s */\n",
-           instruction->file_entry->fields[insn_format]);
-
-  for (cur_field = instruction->fields->first;
-       cur_field->first < insn_size;
-       cur_field = cur_field->next) {
-    if (cur_field->is_string) {
-      insn_bits *bits;
-      int found_rule = 0;
-      /* find any corresponding value */
-      for (bits = expanded_bits;
-          bits != NULL;
-          bits = bits->last) {
-       if (bits->field == cur_field)
-         break;
-      }
-      /* try the cache rule table for what to do */
-      if (get_value_from_cache || put_value_in_cache) {      
-       cache_rules *cache_rule;
-       for (cache_rule = cache_table;
-            cache_rule != NULL;
-            cache_rule = cache_rule->next) {
-         if (strcmp(cur_field->val_string, cache_rule->old_name) == 0) {
-           found_rule = 1;
-           if (cache_rule->valid > 1 && put_value_in_cache)
-             lf_print_c_extraction(file,
-                                   instruction,
-                                   cache_rule->new_name,
-                                   cache_rule->type,
-                                   cache_rule->expression,
-                                   cur_field,
-                                   bits,
-                                   0,
-                                   0);
-           else if (cache_rule->valid == 1)
-             lf_print_c_extraction(file,
-                                   instruction,
-                                   cache_rule->new_name,
-                                   cache_rule->type,
-                                   cache_rule->expression,
-                                   cur_field,
-                                   bits,
-                                   get_value_from_cache,
-                                   put_value_in_cache);
-         }
-       }
-      }
-      if (found_rule == 0)
-       lf_print_c_extraction(file,
-                             instruction,
-                             cur_field->val_string,
-                             0,
-                             0,
-                             cur_field,
-                             bits,
-                             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])) {
-             table_entry_lf_c_line_nr(file, instruction->file_entry);
-             lf_printf(file, "const unsigned %s_is_0 = (", field_name);
-             if (bits != NULL)
-               lf_printf(file, "%d", bits->value);
-             else
-               lf_printf(file, "%s", field_name);
-             lf_printf(file, " == 0);\n");
-             break;
-           }
-           is_0_ptr += strlen("_is_0");
-         }
-       }
-      }
-      /* any thing else ... */
-    }
-  }
-  lf_print_lf_c_line_nr(file);
-}
-
-
-static void
-lf_print_idecode_illegal(lf *file)
-{
-  if (idecode_cache)
-    lf_printf(file, "return idecode_illegal(%s);\n", cache_idecode_actual);
-  else
-    lf_printf(file, "return semantic_illegal(%s);\n", semantic_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",
-             semantic_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)
-{
-  /* Validate: unchecked instruction fields
-
-     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;
-
-      /* 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;
-      }
-      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 (WITH_RESERVED_BITS && (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);
-    }
-  }
-}
-
-
-static void
-lf_print_c_cracker(lf *file,
-                  insn *instruction,
-                  insn_bits *expanded_bits,
-                  opcode_field *opcodes)
-{
-
-  /* function header */
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-
-  lf_print_my_prefix(file,
-                    instruction->file_entry,
-                    1/*putting-value-in-cache*/);
-
-  lf_print_ptrace(file,
-                 1/*putting-value-in-cache*/);
-
-  lf_print_c_validate(file, instruction, opcodes);
-
-  lf_printf(file, "\n");
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-  lf_print_c_extractions(file,
-                        instruction,
-                        expanded_bits,
-                        0/*get_value_from_cache*/,
-                        1/*put_value_in_cache*/);
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-
-  /* return the function propper (main sorts this one out) */
-  lf_printf(file, "\n");
-  lf_printf(file, "/* semantic routine */\n");
-  table_entry_lf_c_line_nr(file, instruction->file_entry);
-  lf_printf(file, "return ");
-  lf_print_function_name(file,
-                        instruction->file_entry->fields[insn_name],
-                        expanded_bits,
-                        function_name_prefix_semantics);
-  lf_printf(file, ";\n");
-
-  lf_print_lf_c_line_nr(file);
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-}
-
-
-static void
-lf_print_c_semantic(lf *file,
-                   insn *instruction,
-                   insn_bits *expanded_bits,
-                   opcode_field *opcodes)
-{
-
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-
-  lf_print_my_prefix(file,
-                    instruction->file_entry,
-                    0/*not putting value in cache*/);
-  lf_printf(file, "unsigned_word nia = cia + %d;\n", insn_size / 8);
-
-  lf_printf(file, "\n");
-  lf_print_c_extractions(file,
-                        instruction,
-                        expanded_bits,
-                        idecode_cache/*get_value_from_cache*/,
-                        0/*put_value_in_cache*/);
-
-  lf_print_ptrace(file,
-                 0/*put_value_in_cache*/);
-
-  /* validate the instruction, if a cache this has already been done */
-  if (!idecode_cache)
-    lf_print_c_validate(file, instruction, opcodes);
-
-  /* generate the profileing call - this is delayed until after the
-     instruction has been verified */
-  lf_printf(file, "\n");
-  lf_printf(file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE)\n");
-  lf_printf(file, "  mon_issue(");
-  lf_print_function_name(file,
-                        instruction->file_entry->fields[insn_name],
-                        NULL,
-                        function_name_prefix_itable);
-  lf_printf(file, ", processor, cia);\n");
-
-  /* generate the code (or at least something */
-  if (instruction->file_entry->annex != NULL) {
-    /* true code */
-    lf_printf(file, "\n");
-    table_entry_lf_c_line_nr(file, instruction->file_entry);
-    lf_printf(file, "{\n");
-    lf_indent(file, +2);
-    lf_print_c_code(file, instruction->file_entry->annex);
-    lf_indent(file, -2);
-    lf_printf(file, "}\n");
-    lf_print_lf_c_line_nr(file);
-  }
-  else if (it_is("nop", instruction->file_entry->fields[insn_flags])) {
-    lf_print_lf_c_line_nr(file);
-  }
-  else if (it_is("f", instruction->file_entry->fields[insn_flags])) {
-    /* unimplemented floating point instruction - call for assistance */
-    lf_printf(file, "\n");
-    lf_printf(file, "/* unimplemented floating point instruction - call for assistance */\n");
-    table_entry_lf_c_line_nr(file, instruction->file_entry);
-    lf_putstr(file, "floating_point_assist_interrupt(processor, cia);\n");
-    lf_print_lf_c_line_nr(file);
-  }
-  else {
-    /* abort so it is implemented now */
-    table_entry_lf_c_line_nr(file, instruction->file_entry);
-    lf_putstr(file, "error(\"%s: unimplemented, cia=0x%x\\n\", my_prefix, cia);\n");
-    lf_print_lf_c_line_nr(file);
-    lf_printf(file, "\n");
-  }
-
-  /* the function footer */
-  lf_printf(file, "return nia;\n");
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-}
-
-static void
-lf_print_c_semantic_function_header(lf *file,
-                                   char *basename,
-                                   insn_bits *expanded_bits)
-{
-  lf_printf(file, "\n");
-  lf_printf(file, "INLINE_SEMANTICS unsigned_word\n");
-  lf_print_function_name(file,
-                        basename,
-                        expanded_bits,
-                        function_name_prefix_semantics);
-  lf_printf(file, "\n(%s)\n",
-           (idecode_cache ? cache_semantic_formal : semantic_formal));
-}
-
-static void
-lf_print_c_semantic_function(lf *file,
-                            insn *instruction,
-                            insn_bits *expanded_bits,
-                            opcode_field *opcodes)
-{
-
-  /* build the semantic routine to execute the instruction */
-  lf_print_c_semantic_function_header(file,
-                                     instruction->file_entry->fields[insn_name],
-                                     expanded_bits);
-  lf_print_c_semantic(file,
-                     instruction,
-                     expanded_bits,
-                     opcodes);
-}
-
-
-static void
-semantics_c_leaf(insn_table *entry,
-                void *data,
-                int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->nr_insn == 1
-        && entry->opcode == NULL
-        && entry->parent != NULL
-        && entry->parent->opcode != NULL);
-  lf_print_c_semantic_function(file,
-                              entry->insns,
-                              entry->expanded_bits,
-                              entry->parent->opcode);
-}
-
-static void
-semantics_c_insn(insn_table *table,
-                void *data,
-                insn *instruction)
-{
-  lf *file = (lf*)data;
-  lf_print_c_semantic_function(file, instruction,
-                              NULL, NULL);
-}
-
-static void
-semantics_c_function(insn_table *table,
-                    void *data,
-                    table_entry *function)
-{
-  lf *file = (lf*)data;
-  if (function->fields[function_type] == NULL
-      || function->fields[function_type][0] == '\0') {
-    lf_print_c_semantic_function_header(file,
-                                       function->fields[function_name],
-                                       NULL);
-  }
-  else {
-    lf_printf(file, "\n");
-    lf_printf(file, "INLINE_SEMANTICS %s\n%s(%s)\n",
-             function->fields[function_type],
-             function->fields[function_name],
-             function->fields[function_param]);
-  }
-  table_entry_lf_c_line_nr(file, function);
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-  lf_print_c_code(file, function->annex);
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-  lf_print_lf_c_line_nr(file);
-}
-
-
-
-static void 
-gen_semantics_c(insn_table *table, lf *file)
-{
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _SEMANTICS_C_\n");
-  lf_printf(file, "#define _SEMANTICS_C_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef STATIC_INLINE_SEMANTICS\n");
-  lf_printf(file, "#define STATIC_INLINE_SEMANTICS STATIC_INLINE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"cpu.h\"\n");
-  lf_printf(file, "#include \"idecode.h\"\n");
-  lf_printf(file, "#include \"semantics.h\"\n");
-  lf_printf(file, "\n");
-
-  /* output a definition (c-code) for all functions */
-  insn_table_traverse_function(table,
-                              file,
-                              semantics_c_function);
-
-  /* output a definition (c-code) for all instructions */
-  if (idecode_expand_semantics)
-    insn_table_traverse_tree(table,
-                            file,
-                            1,
-                            NULL, /* start */
-                            semantics_c_leaf,
-                            NULL, /* end */
-                            NULL); /* padding */
-  else
-    insn_table_traverse_insn(table,
-                            file,
-                            semantics_c_insn);
-
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _SEMANTICS_C_ */\n");
-}
-
-
-/****************************************************************/
-
-static void
-gen_idecode_h(insn_table *table, lf *file)
-{
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _IDECODE_H_\n");
-  lf_printf(file, "#define _IDECODE_H_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef INLINE_IDECODE\n");
-  lf_printf(file, "#define INLINE_IDECODE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"idecode_expression.h\"\n");
-  lf_printf(file, "#include \"idecode_fields.h\"\n");
-  lf_printf(file, "#include \"idecode_branch.h\"\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"icache.h\"\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "typedef unsigned_word idecode_semantic\n(%s);\n",
-           (idecode_cache ? cache_semantic_formal : semantic_formal));
-  lf_printf(file, "\n");
-  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",
-             semantic_formal);
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _IDECODE_H_ */\n");
-}
-
-
-/****************************************************************/
-
-
-static void
-idecode_table_start(insn_table *table,
-                   void *data,
-                   int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-  /* start of the table */
-  if (!table->opcode_rule->use_switch) {
-    lf_printf(file, "\n");
-    lf_printf(file, "static idecode_table_entry ");
-    lf_print_table_name(file, table);
-    lf_printf(file, "[] = {\n");
-  }
-}
-
-static void
-idecode_table_leaf(insn_table *entry,
-                  void *data,
-                  int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->parent != NULL);
-  ASSERT(depth == 0);
-
-  /* add an entry to the table */
-  if (!entry->parent->opcode_rule->use_switch) {
-    if (entry->opcode == NULL) {
-      /* table leaf entry */
-      lf_printf(file, "  /*%d*/ { 0, 0, ", entry->opcode_nr);
-      lf_print_function_name(file,
-                            entry->insns->file_entry->fields[insn_name],
-                            entry->expanded_bits,
-                            (idecode_cache
-                             ? function_name_prefix_idecode
-                             : function_name_prefix_semantics));
-      lf_printf(file, " },\n");
-    }
-    else if (entry->opcode_rule->use_switch) {
-      /* table calling switch statement */
-      lf_printf(file, "  /*%d*/ { -1, 0, ",
-               entry->opcode_nr);
-      lf_print_table_name(file, entry);
-      lf_printf(file, " },\n");
-    }
-    else {
-      /* table `calling' another table */
-      lf_printf(file, "  /*%d*/ { ", entry->opcode_nr);
-      if (entry->opcode->is_boolean)
-       lf_printf(file, "MASK32(%d,%d), 0, ",
-                 i2target(hi_bit_nr, entry->opcode->first),
-                 i2target(hi_bit_nr, entry->opcode->last));
-      else
-       lf_printf(file, "%d, MASK32(%d,%d), ",
-                 insn_size - entry->opcode->last - 1,
-                 i2target(hi_bit_nr, entry->opcode->first),
-                 i2target(hi_bit_nr, entry->opcode->last));
-      lf_print_table_name(file, entry);
-      lf_printf(file, " },\n");
-    }
-  }
-}
-
-static void
-idecode_table_end(insn_table *table,
-                 void *data,
-                 int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-
-  if (!table->opcode_rule->use_switch) {
-    lf_printf(file, "};\n");
-  }
-}
-
-static void
-idecode_table_padding(insn_table *table,
-                     void *data,
-                     int depth,
-                     int opcode_nr)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-
-  if (!table->opcode_rule->use_switch) {
-    lf_printf(file, "  /*%d*/ { 0, 0, %s_illegal },\n",
-             opcode_nr, (idecode_cache ? "idecode" : "semantic"));
-  }
-}
-
-
-/****************************************************************/
-
-
-void lf_print_idecode_switch
-(lf *file, 
- insn_table *table);
-
-
-static void
-idecode_switch_start(insn_table *table,
-               void *data,
-               int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-  ASSERT(table->opcode_rule->use_switch);
-
-  lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
-           i2target(hi_bit_nr, table->opcode->first),
-           i2target(hi_bit_nr, table->opcode->last));
-}
-
-
-static void
-idecode_switch_leaf(insn_table *entry,
-                   void *data,
-                   int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->parent != NULL);
-  ASSERT(depth == 0);
-  ASSERT(entry->parent->opcode_rule->use_switch);
-
-  lf_printf(file, "case %d:\n", entry->opcode_nr);
-  lf_indent(file, +2);
-  {
-    if (entry->opcode == NULL) {
-      /* switch calling leaf */
-      lf_printf(file, "return ");
-      lf_print_function_name(file,
-                            entry->insns->file_entry->fields[insn_name],
-                            entry->expanded_bits,
-                            (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", semantic_actual);
-    }
-    else if (entry->opcode_rule->use_switch) {
-      /* switch calling switch */
-      lf_print_idecode_switch(file, entry);
-    }
-    else {
-      /* switch calling table */
-      lf_printf(file, "return ");
-      lf_print_idecode_table(file, entry);
-    }
-    lf_printf(file, "break;\n");
-  }
-  lf_indent(file, -2);
-}
-
-
-static void
-lf_print_idecode_switch_illegal(lf *file)
-{
-  lf_indent(file, +2);
-  lf_print_idecode_illegal(file);
-  lf_printf(file, "break;\n");
-  lf_indent(file, -2);
-}
-
-static void
-idecode_switch_end(insn_table *table,
-                  void *data,
-                  int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-  ASSERT(table->opcode_rule->use_switch);
+#include "ld-cache.h"
+#include "ld-decode.h"
+#include "ld-insn.h"
 
-  if (table->opcode_rule->use_switch == 1) {
-    lf_printf(file, "default:\n");
-    lf_print_idecode_switch_illegal(file);
-  }
-  lf_printf(file, "}\n");
-}
+#include "igen.h"
 
-static void
-idecode_switch_padding(insn_table *table,
-                      void *data,
-                      int depth,
-                      int opcode_nr)
-{
-  lf *file = (lf*)data;
+#include "gen-model.h"
+#include "gen-icache.h"
+#include "gen-itable.h"
+#include "gen-idecode.h"
+#include "gen-semantics.h"
+#include "gen-support.h"
 
-  ASSERT(depth == 0);
-  ASSERT(table->opcode_rule->use_switch);
+int hi_bit_nr;
+int insn_bit_size = max_insn_bit_size;
 
-  if (table->opcode_rule->use_switch > 1) {
-    lf_printf(file, "case %d:\n", opcode_nr);
-    lf_print_idecode_switch_illegal(file);
-  }
-}
+igen_code code = generate_calls;
 
+int generate_expanded_instructions;
+int icache_size = 1024;
+int generate_smp;
 
-void
-lf_print_idecode_switch(lf *file, 
-                       insn_table *table)
+/****************************************************************/
+
+static int
+print_insn_bits(lf *file, insn_bits *bits)
 {
-  insn_table_traverse_tree(table,
-                          file,
-                          0,
-                          idecode_switch_start,
-                          idecode_switch_leaf,
-                          idecode_switch_end,
-                          idecode_switch_padding);
+  int nr = 0;
+  if (bits == NULL)
+    return nr;
+  nr += print_insn_bits(file, bits->last);
+  nr += lf_putchr(file, '_');
+  nr += lf_putstr(file, bits->field->val_string);
+  if (bits->opcode->is_boolean && bits->value == 0)
+    nr += lf_putint(file, bits->opcode->boolean_constant);
+  else if (!bits->opcode->is_boolean) {
+    if (bits->opcode->last < bits->field->last)
+      nr += lf_putint(file, bits->value << (bits->field->last - bits->opcode->last));
+    else
+      nr += lf_putint(file, bits->value);
+  }
+  return nr;
 }
 
-
-static void
-idecode_expand_if_switch(insn_table *table,
-                        void *data,
-                        int depth)
+extern int
+print_function_name(lf *file,
+                   const char *basename,
+                   insn_bits *expanded_bits,
+                   lf_function_name_prefixes prefix)
 {
-  lf *file = (lf*)data;
+  int nr = 0;
+  /* the prefix */
+  switch (prefix) {
+  case function_name_prefix_semantics:
+    nr += lf_putstr(file, "semantic_");
+    break;
+  case function_name_prefix_idecode:
+    nr += lf_printf(file, "idecode_");
+    break;
+  case function_name_prefix_itable:
+    nr += lf_putstr(file, "itable_");
+    break;
+  case function_name_prefix_icache:
+    nr += lf_putstr(file, "icache_");
+    break;
+  default:
+    break;
+  }
 
-  if (table->opcode_rule->use_switch
-      && table->parent != NULL /* don't expand the top one yet */
-      && !table->parent->opcode_rule->use_switch) {
-    lf_printf(file, "\n");
-    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 : semantic_formal));
-    lf_printf(file, "{\n");
-    {
-      lf_indent(file, +2);
-      lf_print_idecode_switch(file, table);
-      lf_indent(file, -2);
+  /* the function name */
+  {
+    const char *pos;
+    for (pos = basename;
+        *pos != '\0';
+        pos++) {
+      switch (*pos) {
+      case '/':
+      case '-':
+      case '(':
+      case ')':
+       break;
+      case ' ':
+       nr += lf_putchr(file, '_');
+       break;
+      default:
+       nr += lf_putchr(file, *pos);
+       break;
+      }
     }
-    lf_printf(file, "}\n");
   }
-}
-
 
-static void
-lf_print_c_cracker_function(lf *file,
-                           insn *instruction,
-                           insn_bits *expanded_bits,
-                           opcode_field *opcodes)
-{
-  /* if needed, generate code to enter this routine into a cache */
-  lf_printf(file, "\n");
-  lf_printf(file, "STATIC_INLINE_IDECODE idecode_semantic *\n");
-  lf_print_function_name(file,
-                        instruction->file_entry->fields[insn_name],
-                        expanded_bits,
-                        function_name_prefix_idecode);
-  lf_printf(file, "\n(%s)\n", cache_idecode_formal);
+  /* the suffix */
+  if (generate_expanded_instructions)
+    nr += print_insn_bits(file, expanded_bits);
 
-  lf_print_c_cracker(file,
-                    instruction,
-                    expanded_bits,
-                    opcodes);
+  return nr;
 }
 
-static void
-idecode_crack_leaf(insn_table *entry,
-                  void *data,
-                  int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->nr_insn == 1
-        && entry->opcode == NULL
-        && entry->parent != NULL
-        && entry->parent->opcode != NULL);
-  lf_print_c_cracker_function(file,
-                             entry->insns,
-                             entry->expanded_bits,
-                             entry->opcode);
-}
 
-static void
-idecode_crack_insn(insn_table *entry,
-                  void *data,
-                  insn *instruction)
-{
-  lf *file = (lf*)data;
-  lf_print_c_cracker_function(file,
-                             instruction,
-                             NULL,
-                             NULL);
+void
+print_my_defines(lf *file,
+                insn_bits *expanded_bits,
+                table_entry *file_entry)
+{
+  /* #define MY_INDEX xxxxx */
+  lf_indent_suppress(file);
+  lf_printf(file, "#undef MY_INDEX\n");
+  lf_indent_suppress(file);
+  lf_printf(file, "#define MY_INDEX ");
+  print_function_name(file,
+                      file_entry->fields[insn_name],
+                      NULL,
+                      function_name_prefix_itable);
+  lf_printf(file, "\n");
+  /* #define MY_PREFIX xxxxxx */
+  lf_indent_suppress(file);
+  lf_printf(file, "#undef MY_PREFIX\n");
+  lf_indent_suppress(file);
+  lf_printf(file, "#define MY_PREFIX ");
+  print_function_name(file,
+                     file_entry->fields[insn_name],
+                     expanded_bits,
+                     function_name_prefix_none);
+  lf_printf(file, "\n");
 }
 
-static void
-idecode_c_internal_function(insn_table *table,
-                           void *data,
-                           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");
-    table_entry_lf_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_lf_c_line_nr(file);
-    lf_indent(file, -2);
-    lf_printf(file, "}\n");
-  }
+void
+print_itrace(lf *file,
+            table_entry *file_entry,
+            int idecode)
+{
+  lf_print__external_reference(file, file_entry->line_nr, file_entry->file_name);
+  lf_printf(file, "ITRACE(trace_%s, (\"%s %s\\n\"));\n",
+           (idecode ? "idecode" : "semantics"),
+           (idecode ? "idecode" : "semantics"),
+           file_entry->fields[insn_name]);
+  lf_print__internal_reference(file);
 }
 
 
 /****************************************************************/
 
+
 static void
-gen_idecode_c(insn_table *table, lf *file)
+gen_semantics_h(insn_table *table,
+               lf *file,
+               igen_code generate)
 {
-  int depth;
-
-  /* the intro */
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _IDECODE_C_\n");
-  lf_printf(file, "#define _IDECODE_C_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef STATIC_INLINE_IDECODE\n");
-  lf_printf(file, "#define STATIC_INLINE_IDECODE STATIC_INLINE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"cpu.h\"\n");
-  lf_printf(file, "#include \"idecode.h\"\n");
-  lf_printf(file, "#include \"semantics.h\"\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "typedef idecode_semantic *idecode_crack\n(%s);\n",
-           (idecode_cache ? cache_idecode_formal : semantic_formal));
-  lf_printf(file, "\n");
-  lf_printf(file, "typedef struct _idecode_table_entry {\n");
-  lf_printf(file, "  unsigned shift;\n");
-  lf_printf(file, "  unsigned mask;\n");
-  lf_printf(file, "  void *function_or_table;\n");
-  lf_printf(file, "} idecode_table_entry;\n");
-  lf_printf(file, "\n");
+  lf_printf(file, "typedef %s idecode_semantic\n(%s);\n",
+           SEMANTIC_FUNCTION_TYPE,
+           SEMANTIC_FUNCTION_FORMAL);
   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) {
-    if (idecode_expand_semantics)
+  if ((code & generate_calls)) {
+    lf_printf(file, "extern int option_mpc860c0;\n");
+    lf_printf(file, "#define PAGE_SIZE 0x1000\n");
+    lf_printf(file, "\n");
+    lf_printf(file, "PSIM_EXTERN_SEMANTICS(void)\n");
+    lf_printf(file, "semantic_init(device* root);\n");
+    lf_printf(file, "\n");
+    if (generate_expanded_instructions)
       insn_table_traverse_tree(table,
-                              file,
+                              file, NULL,
                               1,
-                              NULL,
-                              idecode_crack_leaf,
-                              NULL,
-                              NULL);
+                              NULL, /* start */
+                              print_semantic_declaration, /* leaf */
+                              NULL, /* end */
+                              NULL); /* padding */
     else
       insn_table_traverse_insn(table,
-                              file,
-                              idecode_crack_insn);
+                              file, NULL,
+                              print_semantic_declaration);
+    
   }
-
-
-  /* output tables where needed */
-  for (depth = insn_table_depth(table);
-       depth > 0;
-       depth--) {
-    insn_table_traverse_tree(table,
-                            file,
-                            1-depth,
-                            idecode_table_start,
-                            idecode_table_leaf,
-                            idecode_table_end,
-                            idecode_table_padding);
+  else {
+    lf_print__this_file_is_empty(file);
   }
-
-  /* output switch functions where needed */
-  insn_table_traverse_tree(table,
-                          file,
-                          1,
-                          idecode_expand_if_switch, /* START */
-                          NULL, NULL, NULL);
-
-  /* output the main idecode routine */
-  lf_printf(file, "\n");
-  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",
-             semantic_formal);
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-  if (table->opcode_rule->use_switch)
-    lf_print_idecode_switch(file, table);
-  else
-    lf_print_idecode_table(file, table);
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif\n");
 }
 
 
-/****************************************************************/
-
 static void
-itable_h_insn(insn_table *entry,
-             void *data,
-             insn *instruction)
+gen_semantics_c(insn_table *table,
+               cache_table *cache_rules,
+               lf *file,
+               igen_code generate)
 {
-  lf *file = (lf*)data;
-  lf_printf(file, "  ");
-  lf_print_function_name(file,
-                        instruction->file_entry->fields[insn_name],
-                        NULL,
-                        function_name_prefix_itable);
-  lf_printf(file, ",\n");
+  if ((code & generate_calls)) {
+    lf_printf(file, "\n");
+    lf_printf(file, "#include \"cpu.h\"\n");
+    lf_printf(file, "#include \"idecode.h\"\n");
+    lf_printf(file, "#include \"semantics.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, "int option_mpc860c0 = 0;\n");
+    lf_printf(file, "\n");
+    lf_printf(file, "PSIM_EXTERN_SEMANTICS(void)\n");
+    lf_printf(file, "semantic_init(device* root)\n");
+    lf_printf(file, "{\n");
+    lf_printf(file, "  option_mpc860c0 = 0;\n");
+    lf_printf(file, "  if (tree_find_property(root, \"/options/mpc860c0\"))\n");
+    lf_printf(file, "    option_mpc860c0 = tree_find_integer_property(root, \"/options/mpc860c0\");\n");
+    lf_printf(file, "    option_mpc860c0 *= 4;   /* convert word count to byte count */\n");
+    lf_printf(file, "}\n");
+    lf_printf(file, "\n");
+    if (generate_expanded_instructions)
+      insn_table_traverse_tree(table,
+                              file, cache_rules,
+                              1,
+                              NULL, /* start */
+                              print_semantic_definition, /* leaf */
+                              NULL, /* end */
+                              NULL); /* padding */
+    else
+      insn_table_traverse_insn(table,
+                              file, cache_rules,
+                              print_semantic_definition);
+    
+  }
+  else {
+    lf_print__this_file_is_empty(file);
+  }
 }
 
 
-static void 
-gen_itable_h(insn_table *table, lf *file)
-{
-
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _ITABLE_H_\n");
-  lf_printf(file, "#define _ITABLE_H_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef INLINE_ITABLE\n");
-  lf_printf(file, "#define INLINE_ITABLE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "\n");
-
-  /* output an enumerated type for each instruction */
-  lf_printf(file, "typedef enum {\n");
-  insn_table_traverse_insn(table,
-                          file,
-                          itable_h_insn);
-  lf_printf(file, "  nr_itable_entries,\n");
-  lf_printf(file, "} itable_index;\n");
-  lf_printf(file, "\n");
-
-  /* output the table that contains the actual instruction info */
-  lf_printf(file, "typedef struct _itable_instruction_info {\n");
-  lf_printf(file, "  itable_index nr;\n");
-  lf_printf(file, "  char *format;\n");
-  lf_printf(file, "  char *form;\n");
-  lf_printf(file, "  char *flags;\n");
-  lf_printf(file, "  char *nmemonic;\n");
-  lf_printf(file, "  char *name;\n");
-  lf_printf(file, "} itable_info;\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "extern itable_info itable[nr_itable_entries];\n");
-
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _ITABLE_C_ */\n");
-
-}
-
 /****************************************************************/
 
-static void
-itable_c_insn(insn_table *entry,
-             void *data,
-             insn *instruction)
-{
-  lf *file = (lf*)data;
-  char **fields = instruction->file_entry->fields;
-  lf_printf(file, "  { ");
-  lf_print_function_name(file,
-                        instruction->file_entry->fields[insn_name],
-                        NULL,
-                        function_name_prefix_itable);
-  lf_printf(file, ",\n");
-  lf_printf(file, "    \"%s\",\n", fields[insn_format]);
-  lf_printf(file, "    \"%s\",\n", fields[insn_form]);
-  lf_printf(file, "    \"%s\",\n", fields[insn_flags]);
-  lf_printf(file, "    \"%s\",\n", fields[insn_nmemonic]);
-  lf_printf(file, "    \"%s\",\n", fields[insn_name]);
-  lf_printf(file, "    },\n");
-}
-
-
-static void 
-gen_itable_c(insn_table *table, lf *file)
-{
-
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _ITABLE_C_\n");
-  lf_printf(file, "#define _ITABLE_C_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef STATIC_INLINE_ITABLE\n");
-  lf_printf(file, "#define STATIC_INLINE_ITABLE STATIC_INLINE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"itable.h\"\n");
-  lf_printf(file, "\n");
-
-  /* output the table that contains the actual instruction info */
-  lf_printf(file, "itable_info itable[nr_itable_entries] = {\n");
-  insn_table_traverse_insn(table,
-                          file,
-                          itable_c_insn);
-  lf_printf(file, "};\n");
-  lf_printf(file, "\n");
-
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _ITABLE_C_ */\n");
-}
-
-/****************************************************************/
 
-static void 
-gen_model_h(insn_table *table, lf *file)
+static void
+gen_icache_h(insn_table *table,
+            lf *file,
+            igen_code generate)
 {
-  model *model_ptr;
-  model_func_unit *func_unit_ptr;
-  int hex_size;
-
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _MODEL_H_\n");
-  lf_printf(file, "#define _MODEL_H_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef INLINE_MODEL\n");
-  lf_printf(file, "#define INLINE_MODEL\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-
-  lf_printf(file, "typedef struct _model_time {\t/* Instruction cycle time */\n");
-  if (table->max_func_unit_mask > 0xffff) {
-    hex_size = 8;
-    lf_printf(file, "  unsigned32 units;\n");
-    lf_printf(file, "  unsigned16 initial;\n");
-    lf_printf(file, "  unsigned16 finish;\n");
-  } else {
-    hex_size = 4;
-    lf_printf(file, "  unsigned16 units;\n");
-    lf_printf(file, "  unsigned8  initial;\n");
-    lf_printf(file, "  unsigned8  finish;\n");
-  }
-  lf_printf(file, "  unsigned32 flags;\n");
-  lf_printf(file, "} model_time;\n");
+  lf_printf(file, "typedef %s idecode_icache\n(%s);\n",
+           ICACHE_FUNCTION_TYPE,
+           ICACHE_FUNCTION_FORMAL);
   lf_printf(file, "\n");
-
-  lf_printf(file, "typedef enum _model_enum {\n");
-  lf_printf(file, "  MODEL_NONE,\n");
-  for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
-    lf_printf(file, "  MODEL_%s,\n", model_ptr->name);
+  if ((code & generate_calls)
+      && (code & generate_with_icache)) {
+    insn_table_traverse_function(table,
+                                file, NULL,
+                                print_icache_internal_function_declaration);
+    if (generate_expanded_instructions)
+      insn_table_traverse_tree(table,
+                              file, NULL,
+                              1,
+                              NULL, /* start */
+                              print_icache_declaration, /* leaf */
+                              NULL, /* end */
+                              NULL); /* padding */
+    else
+      insn_table_traverse_insn(table,
+                              file, NULL,
+                              print_icache_declaration);
+    
   }
-  lf_printf(file, "  nr_models\n");
-  lf_printf(file, "} model_enum;\n");
-  lf_printf(file, "\n");
-
-  for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
-    for (func_unit_ptr = model_ptr->func_unit_start; func_unit_ptr; func_unit_ptr = func_unit_ptr->next) {
-      if (func_unit_ptr->comment) {
-       lf_printf(file, "#define %-*s 0x%.*x  /* %s functional unit */\n",
-                 table->max_func_unit_name_len, func_unit_ptr->name,
-                 hex_size, func_unit_ptr->mask,
-                 func_unit_ptr->comment);
-      } else {
-       lf_printf(file, "#define %-*s 0x%.*x\n",
-                 table->max_func_unit_name_len, func_unit_ptr->name,
-                 hex_size, func_unit_ptr->mask);
-      }
-    }
-    lf_printf(file, "\n");
+  else {
+    lf_print__this_file_is_empty(file);
   }
-
-  lf_printf(file, "extern const char *model_name[ (int)nr_models ];\n");
-  lf_printf(file, "extern const char *const *const model_func_unit_name[ (int)nr_models ];\n");
-  lf_printf(file, "extern const model_time *const model_time_mapping[];\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _MODEL_H_ */\n");
 }
 
-/****************************************************************/
-
-typedef struct _model_c_data model_c_data;
-struct _model_c_data {
-  lf *file;
-  model *model_ptr;
-};
-
 static void
-model_c_insn(insn_table *entry,
-             void *data,
-             insn *instruction)
-{
-  model_c_data *data_ptr = (model_c_data *)data;
-  lf *file = data_ptr->file;
-  model *current_model = data_ptr->model_ptr;
-  table_model_entry *model_ptr = instruction->file_entry->model_first;
-  int i;
-
-  while (model_ptr) {
-    if (model_ptr->fields[insn_model_name] == current_model->name) {
-      lf_printf(file, "  {");
-      for(i = insn_model_unit; i < nr_insn_model_table_fields; i++) {
-       lf_printf(file, " %s,", model_ptr->fields[i]);
-      }
-      lf_printf(file, " },\n");
-      return;
-    }
-
-    model_ptr = model_ptr->next;
-  }
-
-  lf_printf(file, "  { 0 },\n");
-}
-
-static void 
-gen_model_c(insn_table *table, lf *file)
+gen_icache_c(insn_table *table,
+            cache_table *cache_rules,
+            lf *file,
+            igen_code generate)
 {
-  model *model_ptr;
-  model_func_unit *func_unit_ptr;
-  int i;
-
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _MODEL_C_\n");
-  lf_printf(file, "#define _MODEL_C_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef STATIC_INLINE_MODEL\n");
-  lf_printf(file, "#define STATIC_INLINE_MODEL STATIC_INLINE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"cpu.h\"\n");
-  lf_printf(file, "\n");
-
-  lf_printf(file, "/* map model enumeration into printable string */\n");
-  lf_printf(file, "const char *model_name[ (int)nr_models ] = {\n");
-  lf_printf(file, "  \"NONE\",\n");
-  for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
-    lf_printf(file, "  \"%s\",\n", model_ptr->name);
-  }
-  lf_printf(file, "};\n");
-  lf_printf(file, "\n");
-
-  lf_printf(file, "/* Emit each model's individual function unit names */\n");
-  lf_printf(file, "static const char *const model_func_unit_name_NONE[] = {\n");
-  lf_printf(file, "  \"none\",\n");
-  lf_printf(file, "  (const char *)0\n");
-  lf_printf(file, "};\n");
-  lf_printf(file, "\n");
-
-  for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
-    lf_printf(file, "static const char *const model_func_unit_name_%s[] = {\n", model_ptr->name);
-    lf_printf(file, "  \"none\",\n");
-    for (func_unit_ptr = model_ptr->func_unit_start; func_unit_ptr; func_unit_ptr = func_unit_ptr->next) {
-
-      if (func_unit_ptr->comment)
-       lf_printf(file, "  \"%s %s functional unit\",\n", func_unit_ptr->name, func_unit_ptr->comment);
-      else
-       lf_printf(file, "  \"%s\",\n", func_unit_ptr->name);
-
-      for(i = 2; i < func_unit_ptr->number; i++) {
-       if (func_unit_ptr->comment)
-         lf_printf(file, "  \"%s %s functional unit #%d\",\n", func_unit_ptr->name,
-                   func_unit_ptr->comment, i);
-       else
-         lf_printf(file, "  \"%s #%d\",\n", func_unit_ptr->name, i);
-      }
-    }
-
-    lf_printf(file, "  (const char *)0\n");
-    lf_printf(file, "};\n");
+  /* output `internal' invalid/floating-point unavailable functions
+     where needed */
+  if ((code & generate_calls)
+      && (code & generate_with_icache)) {
     lf_printf(file, "\n");
-  }
-
-  lf_printf(file, "/* Array to map model,function unit number to printable string. */\n");
-  lf_printf(file, "const char *const *const model_func_unit_name[] = {\n");
-  lf_printf(file, "  model_func_unit_name_NONE,\n");
-  for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
-    lf_printf(file, "  model_func_unit_name_%s,\n", model_ptr->name);
-  }
-  lf_printf(file, "};\n");
-  lf_printf(file, "\n");
-
-  lf_printf(file, "/* Insn functional unit info */\n");
-  for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
-    model_c_data data;
-
-    lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name);
-    data.file = file;
-    data.model_ptr = model_ptr;
-    insn_table_traverse_insn(table,
-                            (void *)&data,
-                            model_c_insn);
-
-    lf_printf(file, "};\n");
+    lf_printf(file, "#include \"cpu.h\"\n");
+    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");
+    insn_table_traverse_function(table,
+                                file, NULL,
+                                print_icache_internal_function_definition);
     lf_printf(file, "\n");
+    if (generate_expanded_instructions)
+      insn_table_traverse_tree(table,
+                              file, cache_rules,
+                              1,
+                              NULL, /* start */
+                              print_icache_definition, /* leaf */
+                              NULL, /* end */
+                              NULL); /* padding */
+    else
+      insn_table_traverse_insn(table,
+                              file, cache_rules,
+                              print_icache_definition);
+    
   }
-
-  lf_printf(file, "const model_time *const model_time_mapping[] = {\n");
-  lf_printf(file, "  (const model_time *const)0,\n");
-  for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
-    lf_printf(file, "  model_time_%s,\n", model_ptr->name);
+  else {
+    lf_print__this_file_is_empty(file);
   }
-  lf_printf(file, "};\n");
-  lf_printf(file, "\n");
-
-  lf_printf(file, "#endif /* _MODEL_C_ */\n");
-
 }
 
+
 /****************************************************************/
 
 
@@ -3098,134 +345,214 @@ main(int argc,
      char **argv,
      char **envp)
 {
+  cache_table *cache_rules = NULL;
+  lf_file_references file_references = lf_include_references;
+  decode_table *decode_rules = NULL;
+  filter *filters = NULL;
   insn_table *instructions = NULL;
-  icache_tree *cache_fields = NULL;
+  table_include *includes = NULL;
   char *real_file_name = NULL;
+  int is_header = 0;
   int ch;
 
   if (argc == 1) {
     printf("Usage:\n");
     printf("  igen <config-opts> ... <input-opts>... <output-opts>...\n");
     printf("Config options:\n");
-    printf("  -f <filter-out-flag>  eg -f 64 to skip 64bit instructions\n");
-    printf("  -e    Expand (duplicate) semantic functions\n");
-    printf("  -r <icache-size>  Generate cracking cache version\n");
-    printf("  -l    Supress line numbering in output files\n");
-    printf("  -b <bit-size>  Set the number of bits in an instruction\n");
-    printf("  -h <high-bit>  Set the nr of the high (msb bit)\n");
+    printf("  -F <filter-out-flag>  eg -F 64 to skip 64bit instructions\n");
+    printf("  -E                    Expand (duplicate) semantic functions\n");
+    printf("  -I <icache-size>      Generate cracking cache version\n");
+    printf("  -C                    Include semantics in cache functions\n");
+    printf("  -S                    Include insn (instruction) in icache\n");
+    printf("  -R                    Use defines to reference cache vars\n");
+    printf("  -L                    Supress line numbering in output files\n");
+    printf("  -B <bit-size>         Set the number of bits in an instruction\n");
+    printf("  -H <high-bit>         Set the nr of the high (msb bit)\n");
+    printf("  -N <nr-cpus>          Specify the max number of cpus the simulation will support\n");
+    printf("  -J                    Use jumps instead of function calls\n");
+    printf("  -T <mechanism>        Override the mechanism used to decode an instruction\n");
+    printf("                        using <mechanism> instead of what was specified in the\n");
+    printf("                        decode-rules input file\n");
+    printf("\n");
     printf("Input options (ucase version also dumps loaded table):\n");
-    printf("  -[Oo] <opcode-rules>\n");
-    printf("  -[Kk] <cache-rules>\n");
-    printf("  -[Ii] <instruction-table>\n");
+    printf("  -o <decode-rules>\n");
+    printf("  -k <cache-rules>\n");
+    printf("  -i <instruction-table>\n");
+    printf("\n");
     printf("Output options:\n");
-    printf("  -[Cc] <output-file>  output icache.h(C) invalid(c)\n");
-    printf("  -[Dd] <output-file>  output idecode.h(D) idecode.c(d)\n");
-    printf("  -[Mm] <output-file>  output model.h(M) model.c(M)\n");
-    printf("  -[Ss] <output-file>  output schematic.h(S) schematic.c(s)\n");
-    printf("  -[Tt] <table>      output itable.h(T) itable.c(t)\n");
+    printf("  -n <real-name>        Specify the real name of for the next output file\n"); 
+    printf("  -h                   Generate header file\n");
+    printf("  -c <output-file>      output icache\n");
+    printf("  -d <output-file>      output idecode\n");
+    printf("  -m <output-file>      output model\n");
+    printf("  -s <output-file>      output schematic\n");
+    printf("  -t <output-file>      output itable\n");
+    printf("  -f <output-file>      output support functions\n");
   }
 
   while ((ch = getopt(argc, argv,
-                     "leb:h:r:f:I:i:O:o:K:k:M:m:n:S:s:D:d:T:t:C:")) != -1) {
+                     "F:EI:RSLJT:CB:H:N:o:k:i:n:hc:d:m:s:t:f:"))
+        != -1) {
     fprintf(stderr, "\t-%c %s\n", ch, (optarg ? optarg : ""));
     switch(ch) {
-    case 'l':
-      number_lines = 0;
-      break;
-    case 'e':
-      idecode_expand_semantics = 1;
+    case 'C':
+      code |= generate_with_icache;
+      code |= generate_with_semantic_icache;
       break;
-    case 'r':
-      idecode_cache = a2i(optarg);
+    case 'S':
+      code |= generate_with_icache;
+      code |= generate_with_insn_in_icache;
       break;
-    case 'b':
-      insn_size = a2i(optarg);
-      ASSERT(insn_size > 0 && insn_size <= max_insn_size
-            && (hi_bit_nr == insn_size-1 || hi_bit_nr == 0));
+    case 'L':
+      file_references = lf_omit_references;
       break;
-    case 'h':
-      hi_bit_nr = a2i(optarg);
-      ASSERT(hi_bit_nr == insn_size-1 || hi_bit_nr == 0);
+    case 'E':
+      generate_expanded_instructions = 1;
       break;
-    case 'f':
+    case 'G':
       {
-       filter *new_filter = ZALLOC(filter);
-       new_filter->flag = strdup(optarg);
-       new_filter->next = filters;
-       filters = new_filter;
-       break;
-      }
+       int enable_p;
+       char *argp;
+       if (strncmp (optarg, "no-", strlen ("no-")) == 0)
+         {
+           argp = optarg + strlen ("no-");
+           enable_p = 0;
+         }
+       else if (strncmp (optarg, "!", strlen ("!")) == 0)
+         {
+           argp = optarg + strlen ("no-");
+           enable_p = 0;
+         }
+       else
+         {
+           argp = optarg;
+           enable_p = 1;
+         }
+        if (strncmp (argp, "gen-icache", strlen ("gen-icache")) == 0)
+          {
+            switch (argp[strlen ("gen-icache")])
+              {
+              case '=':
+               icache_size = atoi (argp + strlen ("gen-icache") + 1);
+               code |= generate_with_icache;
+                break;
+              case '\0':
+               code |= generate_with_icache;
+                break;
+              default:
+                error (NULL, "Expecting -Ggen-icache or -Ggen-icache=<N>\n");
+              }
+          }
+       }
     case 'I':
+      {
+       table_include **dir = &includes;
+       while ((*dir) != NULL)
+         dir = &(*dir)->next;
+       (*dir) = ZALLOC (table_include);
+       (*dir)->dir = strdup (optarg);
+      }
+      break;
+    case 'N':
+      generate_smp = a2i(optarg);
+      break;
+    case 'R':
+      code |= generate_with_direct_access;
+      break;
+    case 'B':
+      insn_bit_size = a2i(optarg);
+      ASSERT(insn_bit_size > 0 && insn_bit_size <= max_insn_bit_size
+            && (hi_bit_nr == insn_bit_size-1 || hi_bit_nr == 0));
+      break;
+    case 'H':
+      hi_bit_nr = a2i(optarg);
+      ASSERT(hi_bit_nr == insn_bit_size-1 || hi_bit_nr == 0);
+      break;
+    case 'F':
+      filters = new_filter(optarg, filters);
+      break;
+    case 'J':
+      code &= ~generate_calls;
+      code |= generate_jumps;
+      break;
+    case 'T':
+      force_decode_gen_type(optarg);
+      break;
     case 'i':
-      ASSERT(opcode_table != NULL);
-      ASSERT(cache_table != NULL);
-      instructions = insn_table_load_insns(optarg);
+      if (decode_rules == NULL) {
+       fprintf(stderr, "Must specify decode tables\n");
+       exit (1);
+      }
+      instructions = load_insn_table(optarg, decode_rules, filters, includes,
+                                    &cache_rules);
       fprintf(stderr, "\texpanding ...\n");
       insn_table_expand_insns(instructions);
-      fprintf(stderr, "\tcache fields ...\n");
-      cache_fields = insn_table_cache_fields(instructions);
-      if (ch == 'I') {
-       dump_traverse(instructions);
-       dump_insn_table(instructions, 0, 1);
-      }
       break;
-    case 'O':
     case 'o':
-      opcode_table = load_opcode_rules(optarg);
-      if (ch == 'O')
-       dump_opcode_rules(opcode_table, 0);
+      decode_rules = load_decode_table(optarg, hi_bit_nr);
       break;
-    case 'K':
     case 'k':
-      cache_table = load_cache_rules(optarg);
-      if (ch == 'K')
-       dump_cache_rules(cache_table, 0);
+      cache_rules = load_cache_table(optarg, hi_bit_nr);
       break;
     case 'n':
       real_file_name = strdup(optarg);
       break;
-    case 'S':
+    case 'h':
+      is_header = 1;
+      break;
     case 's':
-    case 'D':
     case 'd':
-    case 'M':
     case 'm':
-    case 'T':
     case 't':
-    case 'C':
+    case 'f':
+    case 'c':
       {
-       lf *file = lf_open(optarg, real_file_name, number_lines);
+       lf *file = lf_open(optarg, real_file_name, file_references,
+                          (is_header ? lf_is_h : lf_is_c),
+                          argv[0]);
+       lf_print__file_start(file);
        ASSERT(instructions != NULL);
        switch (ch) {
-       case 'S':
-         gen_semantics_h(instructions, file);
-         break;
        case 's':
-         gen_semantics_c(instructions, file);
-         break;
-       case 'D':
-         gen_idecode_h(instructions, file);
+         if(is_header)
+           gen_semantics_h(instructions, file, code);
+         else
+           gen_semantics_c(instructions, cache_rules, file, code);
          break;
        case 'd':
-         gen_idecode_c(instructions, file);
-         break;
-       case 'M':
-         gen_model_h(instructions, file);
+         if (is_header)
+           gen_idecode_h(file, instructions, cache_rules);
+         else
+           gen_idecode_c(file, instructions, cache_rules);
          break;
        case 'm':
-         gen_model_c(instructions, file);
-         break;
-       case 'T':
-         gen_itable_h(instructions, file);
+         if (is_header)
+           gen_model_h(instructions, file);
+         else
+           gen_model_c(instructions, file);
          break;
        case 't':
-         gen_itable_c(instructions, file);
+         if (is_header)
+           gen_itable_h(instructions, file);
+         else
+           gen_itable_c(instructions, file);
+         break;
+       case 'f':
+         if (is_header)
+           gen_support_h(instructions, file);
+         else
+           gen_support_c(instructions, file);
          break;
-       case 'C':
-         gen_icache_h(cache_fields, file);
+       case 'c':
+         if (is_header)
+           gen_icache_h(instructions, file, code);
+         else
+           gen_icache_c(instructions, cache_rules, file, code);
          break;
        }
+       lf_print__file_finish(file);
        lf_close(file);
+       is_header = 0;
       }
       real_file_name = NULL;
       break;
This page took 0.079135 seconds and 4 git commands to generate.