]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - sim/ppc/igen.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / sim / ppc / igen.c
index 3db56c06bfbf5c9c1a30e1f9e7d9a8bdbf54b7d8..4b9ae36f0f25fb4c426d5795f805b1068fe0ff43 100644 (file)
  
     */
 
-#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,
-};
-
-int hi_bit_nr = 0;
-int insn_size = max_insn_size;
-int idecode_expand_semantics = 0;
-int idecode_cache = 0;
-int number_lines = 1;
-
-
-/****************************************************************/
-
-
-char *cache_idecode_formal = "cpu *processor,\n instruction_word instruction,\n unsigned_word cia,\n idecode_cache *cache_entry";
-char *cache_idecode_actual = "processor, instruction, cia, cache_entry";
-
-char *cache_semantic_formal = "cpu *processor,\n idecode_cache *cache_entry,\n unsigned_word cia";
-char *cache_semantic_actual = "processor, entry, cia";
-
-char *semantic_formal = "cpu *processor,\n instruction_word instruction,\n unsigned_word cia";
-char *semantic_actual = "processor, instruction, cia";
-
-
-
-/****************************************************************/
-
-
-typedef struct _filter filter;
-struct _filter {
-  char *flag;
-  filter *next;
-};
-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;
-};
-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);
-  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;
-};
-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);
-  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);
-  
-
-}
-
-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()
-{
-  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;
-char *insn_field_name[nr_insn_table_fields] = {
-  "format", "form", "flags", "nmemonic", "name", "comments"
-};
-
-typedef enum {
-  function_type = insn_format,
-  function_name = insn_name,
-  function_param = insn_comment,
-} function_table_fields;
-
-
-typedef struct _insn insn;
-struct _insn {
-  table_entry *file_entry;
-  insn_fields *fields;
-  insn *next;
-};
-
-typedef struct _insn_table insn_table;
-struct _insn_table {
-  int opcode_nr;
-  insn_bits *expanded_bits;
-  int nr_insn;
-  insn *insns;
-  insn *functions;
-  opcode_rules *opcode_rule;
-  opcode_field *opcode;
-  int nr_entries;
-  insn_table *entries;
-  insn_table *sibling;
-  insn_table *parent;
-};
-
-
-
-static void
-insn_table_insert_function(insn_table *table,
-                          table_entry *file_entry)
-{
-  insn **ptr_to_cur_function = &table->functions;
-
-  /* create a new function */
-  insn *new_function = ZALLOC(insn);
-  new_function->file_entry = file_entry;
-
-  /* append it to the end of the function list */
-  while (*ptr_to_cur_function != NULL) {
-    ptr_to_cur_function = &(*ptr_to_cur_function)->next;
-  }
-  *ptr_to_cur_function = new_function;
-}
-
-
-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;
-
-  /* create a new instruction */
-  insn *new_insn = ZALLOC(insn);
-  new_insn->file_entry = file_entry;
-  new_insn->fields = fields;
-
-  /* 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;
-  }
-
-  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);
-  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 {
-      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 ((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);
-}
 
 
+#include <getopt.h>
 
-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");
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+#include "config.h"
 
-  /* output a definition (c-code) for all functions */
-  insn_table_traverse_function(table,
-                              file,
-                              semantics_c_function);
+#include "filter.h"
 
-  /* 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);
+#include "ld-decode.h"
+#include "ld-cache.h"
+#include "ld-insn.h"
 
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _SEMANTICS_C_ */\n");
-}
+#include "igen.h"
 
+#include "gen-model.h"
+#include "gen-icache.h"
+#include "gen-itable.h"
+#include "gen-idecode.h"
+#include "gen-semantics.h"
+#include "gen-support.h"
 
-/****************************************************************/
+int hi_bit_nr;
+int insn_bit_size = max_insn_bit_size;
 
-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");
-}
+igen_code code = generate_calls;
 
+int generate_expanded_instructions;
+int icache_size = 1024;
+int generate_smp;
 
 /****************************************************************/
 
-
-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)
+static int
+print_insn_bits(lf *file, insn_bits *bits)
 {
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-
-  if (!table->opcode_rule->use_switch) {
-    lf_printf(file, "};\n");
+  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_table_padding(insn_table *table,
-                     void *data,
-                     int depth,
-                     int opcode_nr)
+extern int
+print_function_name(lf *file,
+                   const char *basename,
+                   insn_bits *expanded_bits,
+                   lf_function_name_prefixes prefix)
 {
-  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"));
+  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;
   }
-}
-
-
-/****************************************************************/
-
-
-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);
+  /* the function name */
   {
-    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);
+    const char *pos;
+    for (pos = basename;
+        *pos != '\0';
+        pos++) {
+      switch (*pos) {
+      case '/':
+      case '-':
+       break;
+      case ' ':
+       nr += lf_putchr(file, '_');
+       break;
+      default:
+       nr += lf_putchr(file, *pos);
+       break;
+      }
     }
-    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);
+  /* the suffix */
+  if (generate_expanded_instructions)
+    nr += print_insn_bits(file, expanded_bits);
 
-  if (table->opcode_rule->use_switch == 1) {
-    lf_printf(file, "default:\n");
-    lf_print_idecode_switch_illegal(file);
-  }
-  lf_printf(file, "}\n");
+  return nr;
 }
 
-static void
-idecode_switch_padding(insn_table *table,
-                      void *data,
-                      int depth,
-                      int opcode_nr)
-{
-  lf *file = (lf*)data;
-
-  ASSERT(depth == 0);
-  ASSERT(table->opcode_rule->use_switch);
 
-  if (table->opcode_rule->use_switch > 1) {
-    lf_printf(file, "case %d:\n", opcode_nr);
-    lf_print_idecode_switch_illegal(file);
-  }
+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");
 }
 
 
 void
-lf_print_idecode_switch(lf *file, 
-                       insn_table *table)
+print_itrace(lf *file,
+            table_entry *file_entry,
+            int idecode)
 {
-  insn_table_traverse_tree(table,
-                          file,
-                          0,
-                          idecode_switch_start,
-                          idecode_switch_leaf,
-                          idecode_switch_end,
-                          idecode_switch_padding);
+  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
-idecode_expand_if_switch(insn_table *table,
-                        void *data,
-                        int depth)
-{
-  lf *file = (lf*)data;
-
-  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);
-    }
-    lf_printf(file, "}\n");
-  }
-}
+/****************************************************************/
 
 
 static void
-lf_print_c_cracker_function(lf *file,
-                           insn *instruction,
-                           insn_bits *expanded_bits,
-                           opcode_field *opcodes)
+gen_semantics_h(insn_table *table,
+               lf *file,
+               igen_code generate)
 {
-  /* if needed, generate code to enter this routine into a cache */
+  lf_printf(file, "typedef %s idecode_semantic\n(%s);\n",
+           SEMANTIC_FUNCTION_TYPE,
+           SEMANTIC_FUNCTION_FORMAL);
   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);
-
-  lf_print_c_cracker(file,
-                    instruction,
-                    expanded_bits,
-                    opcodes);
-}
-
-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);
+  if ((code & generate_calls)) {
+    if (generate_expanded_instructions)
+      insn_table_traverse_tree(table,
+                              file, NULL,
+                              1,
+                              NULL, /* start */
+                              print_semantic_declaration, /* leaf */
+                              NULL, /* end */
+                              NULL); /* padding */
+    else
+      insn_table_traverse_insn(table,
+                              file, NULL,
+                              print_semantic_declaration);
+    
+  }
+  else {
+    lf_print__this_file_is_empty(file);
+  }
 }
 
-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);
-}
 
 static void
-idecode_c_internal_function(insn_table *table,
-                           void *data,
-                           table_entry *function)
+gen_semantics_c(insn_table *table,
+               cache_table *cache_rules,
+               lf *file,
+               igen_code generate)
 {
-  lf *file = (lf*)data;
-  ASSERT(idecode_cache != 0);
-  if (it_is("internal", function->fields[insn_flags])) {
+  if ((code & generate_calls)) {
     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");
+    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 \"support.h\"\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_idecode_c(insn_table *table, lf *file)
+gen_icache_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, "typedef %s idecode_icache\n(%s);\n",
+           ICACHE_FUNCTION_TYPE,
+           ICACHE_FUNCTION_FORMAL);
   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, "\n");
-
-  /* output `internal' invalid/floating-point unavailable functions
-     where needed */
-  if (idecode_cache) {
+  if ((code & generate_calls)
+      && (code & generate_with_icache)) {
     insn_table_traverse_function(table,
-                                file,
-                                idecode_c_internal_function);
-  }
-
-  /* output cracking functions where needed */
-  if (idecode_cache) {
-    if (idecode_expand_semantics)
+                                file, NULL,
+                                print_icache_internal_function_declaration);
+    if (generate_expanded_instructions)
       insn_table_traverse_tree(table,
-                              file,
+                              file, NULL,
                               1,
-                              NULL,
-                              idecode_crack_leaf,
-                              NULL,
-                              NULL);
+                              NULL, /* start */
+                              print_icache_declaration, /* leaf */
+                              NULL, /* end */
+                              NULL); /* padding */
     else
       insn_table_traverse_insn(table,
-                              file,
-                              idecode_crack_insn);
+                              file, NULL,
+                              print_icache_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)
-{
-  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");
-}
-
-
-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)
+gen_icache_c(insn_table *table,
+            cache_table *cache_rules,
+            lf *file,
+            igen_code generate)
 {
-  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");
+  /* output `internal' invalid/floating-point unavailable functions
+     where needed */
+  if ((code & generate_calls)
+      && (code & generate_with_icache)) {
+    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, "#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);
+    
+  }
+  else {
+    lf_print__this_file_is_empty(file);
+  }
 }
 
 
-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");
-
-}
-
 /****************************************************************/
 
 
@@ -2733,125 +319,166 @@ 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;
   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("\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 <opcode-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("  -[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:n:S:s:D:d:T:t:C:")) != -1) {
+                     "F:EI:RSLJCB: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;
+    case 'C':
+      code |= generate_with_icache;
+      code |= generate_with_semantic_icache;
       break;
-    case 'e':
-      idecode_expand_semantics = 1;
+    case 'S':
+      code |= generate_with_icache;
+      code |= generate_with_insn_in_icache;
       break;
-    case 'r':
-      idecode_cache = a2i(optarg);
+    case 'L':
+      file_references = lf_omit_references;
       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 'E':
+      generate_expanded_instructions = 1;
       break;
-    case 'h':
+    case 'I':
+      icache_size = a2i(optarg);
+      code |= generate_with_icache;
+      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_size-1 || hi_bit_nr == 0);
+      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 'f':
-      {
-       filter *new_filter = ZALLOC(filter);
-       new_filter->flag = strdup(optarg);
-       new_filter->next = filters;
-       filters = new_filter;
-       break;
-      }
-    case 'I':
     case 'i':
-      ASSERT(opcode_table != NULL);
-      ASSERT(cache_table != NULL);
-      instructions = insn_table_load_insns(optarg);
+      if (decode_rules == NULL || cache_rules == NULL) {
+       fprintf(stderr, "Must specify decode and cache tables\n");
+       exit (1);
+      }
+      instructions = load_insn_table(optarg, decode_rules, filters);
       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 'T':
+    case 'm':
     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);
+         if (is_header)
+           gen_idecode_h(file, instructions, cache_rules);
+         else
+           gen_idecode_c(file, instructions, cache_rules);
          break;
-       case 'T':
-         gen_itable_h(instructions, file);
+       case 'm':
+         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;