OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [cpu/] [or32/] [generate.c] - Diff between revs 121 and 220

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 121 Rev 220
/* generate.c -- generates file execgen.c from instruction set
/* generate.c -- generates file execgen.c from instruction set
 
 
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
   Copyright (C) 2008 Embecosm Limited
   Copyright (C) 2008 Embecosm Limited
 
 
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
 
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
 
 
   This program is free software; you can redistribute it and/or modify it
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the Free
   under the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 3 of the License, or (at your option)
   Software Foundation; either version 3 of the License, or (at your option)
   any later version.
   any later version.
 
 
   This program is distributed in the hope that it will be useful, but WITHOUT
   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.
   more details.
 
 
   You should have received a copy of the GNU General Public License along
   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
/* This program is commented throughout in a fashion suitable for processing
/* This program is commented throughout in a fashion suitable for processing
   with Doxygen. */
   with Doxygen. */
 
 
 
 
/* Autoconf and/or portability configuration */
/* Autoconf and/or portability configuration */
#include "config.h"
#include "config.h"
#include "port.h"
#include "port.h"
 
 
/* System includes */
/* System includes */
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdarg.h>
 
 
/* Package includes */
/* Package includes */
#include "opcode/or32.h"
#include "opcode/or32.h"
 
 
static char *in_file;
static char *in_file;
static char *out_file;
static char *out_file;
 
 
/* Whether this instruction stores something in register */
/* Whether this instruction stores something in register */
static int write_to_reg;
static int write_to_reg;
 
 
static int out_lines = 0;
static int out_lines = 0;
 
 
static int shift_fprintf(int level, FILE *f, const char *fmt, ...)
static int shift_fprintf(int level, FILE *f, const char *fmt, ...)
{
{
  va_list ap;
  va_list ap;
  int i;
  int i;
 
 
  va_start(ap, fmt);
  va_start(ap, fmt);
  for(i = 0; i < level; i++)
  for(i = 0; i < level; i++)
    fprintf(f, "  ");
    fprintf(f, "  ");
 
 
  i = vfprintf(f, fmt, ap);
  i = vfprintf(f, fmt, ap);
  va_end(ap);
  va_end(ap);
 
 
  out_lines++;
  out_lines++;
  return i + (level * 2);
  return i + (level * 2);
}
}
 
 
/* Generates a execute sequence for one instruction */
/* Generates a execute sequence for one instruction */
int output_function (FILE *fo, const char *func_name, int level)
int output_function (FILE *fo, const char *func_name, int level)
{
{
  FILE *fi;
  FILE *fi;
  int olevel;
  int olevel;
  int line_num = 0;
  int line_num = 0;
 
 
  if ((fi = fopen (in_file, "rt")) == NULL) {
  if ((fi = fopen (in_file, "rt")) == NULL) {
    printf("could not open file\n");
    printf("could not open file\n");
    return 1;
    return 1;
  }
  }
 
 
  while (!feof (fi)) {
  while (!feof (fi)) {
    char line[10000], *str = line;
    char line[10000], *str = line;
    char *res;
    char *res;
 
 
    res = fgets (str, sizeof (line), fi);
    res = fgets (str, sizeof (line), fi);
 
 
    if (NULL == res)
    if (NULL == res)
      {
      {
        fclose (fi);                    /* Mark Jarvin patch */
        fclose (fi);                    /* Mark Jarvin patch */
        return  1;
        return  1;
      }
      }
 
 
    line[sizeof (line) - 1] = 0;
    line[sizeof (line) - 1] = 0;
    line_num++;
    line_num++;
    if (strncmp (str, "INSTRUCTION (", 13) == 0) {
    if (strncmp (str, "INSTRUCTION (", 13) == 0) {
      char *s;
      char *s;
      str += 13;
      str += 13;
      while (isspace (*str)) str++;
      while (isspace (*str)) str++;
      s = str;
      s = str;
      while (*s && *s != ')') s++;
      while (*s && *s != ')') s++;
      *s = 0;
      *s = 0;
      while (isspace(*(s - 1))) s--;
      while (isspace(*(s - 1))) s--;
      *s = 0;
      *s = 0;
      if (strcmp (str, func_name) == 0) {
      if (strcmp (str, func_name) == 0) {
        olevel = 1;
        olevel = 1;
        str += strlen (str) + 1;
        str += strlen (str) + 1;
        while (isspace (*str)) str++;
        while (isspace (*str)) str++;
        s = str;
        s = str;
        while (*s && *s != '\n' && *s != '\r') s++;
        while (*s && *s != '\n' && *s != '\r') s++;
        *s = 0;
        *s = 0;
        while (isspace(*(s - 1))) s--;
        while (isspace(*(s - 1))) s--;
        *s = 0;
        *s = 0;
        /*shift_fprintf (level, fo, "#line %i \"%s\"\n", line_num, in_file);*/
        /*shift_fprintf (level, fo, "#line %i \"%s\"\n", line_num, in_file);*/
        shift_fprintf (level, fo, "%s", str);
        shift_fprintf (level, fo, "%s", str);
        shift_fprintf (level, fo, "   /* \"%s\" */\n", func_name);
        shift_fprintf (level, fo, "   /* \"%s\" */\n", func_name);
        do {
        do {
          res = fgets (line, sizeof (line), fi);
          res = fgets (line, sizeof (line), fi);
 
 
          if (NULL == res)
          if (NULL == res)
            {
            {
              fclose (fi);
              fclose (fi);
              return  1;
              return  1;
            }
            }
 
 
          line[sizeof(line) - 1] = 0;
          line[sizeof(line) - 1] = 0;
          for (str = line; *str; str++) {
          for (str = line; *str; str++) {
            if (*str == '{') olevel++;
            if (*str == '{') olevel++;
            else if (*str == '}') olevel--;
            else if (*str == '}') olevel--;
          }
          }
          shift_fprintf (level, fo, "%s", line);
          shift_fprintf (level, fo, "%s", line);
        } while (olevel);
        } while (olevel);
        fclose(fi);
        fclose(fi);
        /*shift_fprintf (level, fo, "#line %i \"%s\"\n", out_lines, out_file);*/
        /*shift_fprintf (level, fo, "#line %i \"%s\"\n", out_lines, out_file);*/
        return 0;
        return 0;
      }
      }
    }
    }
  }
  }
  shift_fprintf (level, fo, "%s ();\n", func_name);
  shift_fprintf (level, fo, "%s ();\n", func_name);
 
 
  fclose(fi);
  fclose(fi);
  return 0;
  return 0;
}
}
 
 
/* Parses operands. */
/* Parses operands. */
 
 
static int
static int
gen_eval_operands (FILE *fo, int insn_index, int level)
gen_eval_operands (FILE *fo, int insn_index, int level)
{
{
  struct insn_op_struct *opd = op_start[insn_index];
  struct insn_op_struct *opd = op_start[insn_index];
  int i;
  int i;
  int num_ops;
  int num_ops;
  int nbits = 0;
  int nbits = 0;
  int set_param = 0;
  int set_param = 0;
  int dis = 0;
  int dis = 0;
  int sbit;
  int sbit;
  int dis_op = -1;
  int dis_op = -1;
 
 
  write_to_reg = 0;
  write_to_reg = 0;
 
 
  shift_fprintf (level, fo, "uorreg_t ");
  shift_fprintf (level, fo, "uorreg_t ");
 
 
  /* Count number of operands */
  /* Count number of operands */
  for (i = 0, num_ops = 0;; i++) {
  for (i = 0, num_ops = 0;; i++) {
    if (!(opd[i].type & OPTYPE_OP))
    if (!(opd[i].type & OPTYPE_OP))
      continue;
      continue;
    if (opd[i].type & OPTYPE_DIS)
    if (opd[i].type & OPTYPE_DIS)
      continue;
      continue;
    if (num_ops)
    if (num_ops)
      fprintf(fo, ", ");
      fprintf(fo, ", ");
    fprintf(fo, "%c", 'a' + num_ops);
    fprintf(fo, "%c", 'a' + num_ops);
    num_ops++;
    num_ops++;
    if (opd[i].type & OPTYPE_LAST)
    if (opd[i].type & OPTYPE_LAST)
      break;
      break;
  }
  }
 
 
  fprintf (fo, ";\n");
  fprintf (fo, ";\n");
 
 
  shift_fprintf (level, fo, "/* Number of operands: %i */\n", num_ops);
  shift_fprintf (level, fo, "/* Number of operands: %i */\n", num_ops);
 
 
  i = 0;
  i = 0;
  num_ops = 0;
  num_ops = 0;
  do {
  do {
/*
/*
    printf("opd[%i].type<last> = %c\n", i, opd->type & OPTYPE_LAST ? '1' : '0');    printf("opd[%i].type<op> = %c\n", i, opd->type & OPTYPE_OP ? '1' : '0');
    printf("opd[%i].type<last> = %c\n", i, opd->type & OPTYPE_LAST ? '1' : '0');    printf("opd[%i].type<op> = %c\n", i, opd->type & OPTYPE_OP ? '1' : '0');
    printf("opd[%i].type<reg> = %c\n", i, opd->type & OPTYPE_REG ? '1' : '0');
    printf("opd[%i].type<reg> = %c\n", i, opd->type & OPTYPE_REG ? '1' : '0');
    printf("opd[%i].type<sig> = %c\n", i, opd->type & OPTYPE_SIG ? '1' : '0');
    printf("opd[%i].type<sig> = %c\n", i, opd->type & OPTYPE_SIG ? '1' : '0');
    printf("opd[%i].type<dis> = %c\n", i, opd->type & OPTYPE_DIS ? '1' : '0');
    printf("opd[%i].type<dis> = %c\n", i, opd->type & OPTYPE_DIS ? '1' : '0');
    printf("opd[%i].type<shr> = %i\n", i, opd->type & OPTYPE_SHR);
    printf("opd[%i].type<shr> = %i\n", i, opd->type & OPTYPE_SHR);
    printf("opd[%i].type<sbit> = %i\n", i, (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR);
    printf("opd[%i].type<sbit> = %i\n", i, (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR);
    printf("opd[%i].data = %i\n", i, opd->data);
    printf("opd[%i].data = %i\n", i, opd->data);
*/
*/
 
 
    if (!nbits)
    if (!nbits)
      shift_fprintf (level, fo, "%c = (insn >> %i) & 0x%x;\n", 'a' + num_ops,
      shift_fprintf (level, fo, "%c = (insn >> %i) & 0x%x;\n", 'a' + num_ops,
                     opd->type & OPTYPE_SHR, (1 << opd->data) - 1);
                     opd->type & OPTYPE_SHR, (1 << opd->data) - 1);
    else
    else
      shift_fprintf (level, fo, "%c |= ((insn >> %i) & 0x%x) << %i;\n",
      shift_fprintf (level, fo, "%c |= ((insn >> %i) & 0x%x) << %i;\n",
                     'a' + num_ops, opd->type & OPTYPE_SHR,
                     'a' + num_ops, opd->type & OPTYPE_SHR,
                     (1 << opd->data) - 1, nbits);
                     (1 << opd->data) - 1, nbits);
 
 
    nbits += opd->data;
    nbits += opd->data;
 
 
    if ((opd->type & OPTYPE_DIS) && (opd->type & OPTYPE_OP)) {
    if ((opd->type & OPTYPE_DIS) && (opd->type & OPTYPE_OP)) {
      sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
      sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
      if (opd->type & OPTYPE_SIG)
      if (opd->type & OPTYPE_SIG)
        shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
        shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
                       'a' + num_ops, 1 << sbit, 'a' + num_ops,
                       'a' + num_ops, 1 << sbit, 'a' + num_ops,
                       0xffffffff << sbit);
                       0xffffffff << sbit);
      opd++;
      opd++;
      shift_fprintf (level, fo, "*(orreg_t *)&%c += (orreg_t)cpu_state.reg[(insn >> %i) & 0x%x];\n",
      shift_fprintf (level, fo, "*(orreg_t *)&%c += (orreg_t)cpu_state.reg[(insn >> %i) & 0x%x];\n",
                     'a' + num_ops, opd->type & OPTYPE_SHR,
                     'a' + num_ops, opd->type & OPTYPE_SHR,
                     (1 << opd->data) - 1);
                     (1 << opd->data) - 1);
      dis = 1;
      dis = 1;
      dis_op = num_ops;
      dis_op = num_ops;
    }
    }
 
 
    if (opd->type & OPTYPE_OP) {
    if (opd->type & OPTYPE_OP) {
      sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
      sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
      if (opd->type & OPTYPE_SIG)
      if (opd->type & OPTYPE_SIG)
        shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
        shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
                       'a' + num_ops, 1 << sbit, 'a' + num_ops,
                       'a' + num_ops, 1 << sbit, 'a' + num_ops,
                       0xffffffff << sbit);
                       0xffffffff << sbit);
      if ((opd->type & OPTYPE_REG) && !dis) {
      if ((opd->type & OPTYPE_REG) && !dis) {
        if(!i) {
        if(!i) {
          shift_fprintf (level, fo, "#define SET_PARAM0(val) cpu_state.reg[a] = val\n");
          shift_fprintf (level, fo, "#define SET_PARAM0(val) cpu_state.reg[a] = val\n");
          shift_fprintf (level, fo, "#define REG_PARAM0  a\n");
          shift_fprintf (level, fo, "#define REG_PARAM0  a\n");
          set_param = 1;
          set_param = 1;
        }
        }
        shift_fprintf (level, fo, "#define PARAM%i cpu_state.reg[%c]\n", num_ops,
        shift_fprintf (level, fo, "#define PARAM%i cpu_state.reg[%c]\n", num_ops,
                      'a' + num_ops);
                      'a' + num_ops);
        if(opd->type & OPTYPE_DST)
        if(opd->type & OPTYPE_DST)
          write_to_reg = 1;
          write_to_reg = 1;
      } else {
      } else {
        shift_fprintf (level, fo, "#define PARAM%i %c\n", num_ops,
        shift_fprintf (level, fo, "#define PARAM%i %c\n", num_ops,
                       'a' + num_ops);
                       'a' + num_ops);
      }
      }
      num_ops++;
      num_ops++;
      nbits = 0;
      nbits = 0;
      dis = 0;
      dis = 0;
    }
    }
 
 
    if ((opd->type & OPTYPE_LAST))
    if ((opd->type & OPTYPE_LAST))
      break;
      break;
    opd++;
    opd++;
    i++;
    i++;
  } while (1);
  } while (1);
 
 
  output_function (fo, or32_opcodes[insn_index].function_name, level);
  output_function (fo, or32_opcodes[insn_index].function_name, level);
 
 
  if (set_param)
  if (set_param)
    {
    {
      shift_fprintf (level, fo, "#undef SET_PARAM0\n");
      shift_fprintf (level, fo, "#undef SET_PARAM0\n");
      shift_fprintf (level, fo, "#undef REG_PARAM0\n");
      shift_fprintf (level, fo, "#undef REG_PARAM0\n");
    }
    }
 
 
  for (i = 0; i < num_ops; i++)
  for (i = 0; i < num_ops; i++)
    shift_fprintf (level, fo, "#undef PARAM%i\n", i);
    shift_fprintf (level, fo, "#undef PARAM%i\n", i);
 
 
  return dis_op;
  return dis_op;
}
}
 
 
/* Generates decode and execute for one instruction instance */
/* Generates decode and execute for one instruction instance */
static int output_call (FILE *fo, int index, int level)
static int output_call (FILE *fo, int index, int level)
{
{
  int dis_op = -1;
  int dis_op = -1;
 
 
  /*printf ("%i:%s\n", index, insn_name (index));*/
  /*printf ("%i:%s\n", index, insn_name (index));*/
 
 
  shift_fprintf (level++, fo, "{\n");
  shift_fprintf (level++, fo, "{\n");
 
 
  if (index >= 0)
  if (index >= 0)
    dis_op = gen_eval_operands (fo, index, level);
    dis_op = gen_eval_operands (fo, index, level);
 
 
  if (index < 0) output_function (fo, "l_invalid", level);
  if (index < 0) output_function (fo, "l_invalid", level);
 
 
  fprintf (fo, "\n");
  fprintf (fo, "\n");
 
 
  shift_fprintf (level++, fo, "if (do_stats) {\n");
  shift_fprintf (level++, fo, "if (do_stats) {\n");
 
 
  if (dis_op >= 0)
  if (dis_op >= 0)
    shift_fprintf (level, fo, "cpu_state.insn_ea = %c;\n", 'a' + dis_op);
    shift_fprintf (level, fo, "cpu_state.insn_ea = %c;\n", 'a' + dis_op);
 
 
  shift_fprintf (level, fo, "current->insn_index = %i;   /* \"%s\" */\n", index,
  shift_fprintf (level, fo, "current->insn_index = %i;   /* \"%s\" */\n", index,
                 insn_name (index));
                 insn_name (index));
 
 
  shift_fprintf (level, fo, "analysis(current);\n");
  shift_fprintf (level, fo, "analysis(current);\n");
  shift_fprintf (--level, fo, "}\n");
  shift_fprintf (--level, fo, "}\n");
 
 
  if (write_to_reg)
  if (write_to_reg)
    shift_fprintf (level, fo, "cpu_state.reg[0] = 0; /* Repair in case we changed it */\n");
    shift_fprintf (level, fo, "cpu_state.reg[0] = 0; /* Repair in case we changed it */\n");
  shift_fprintf (--level, fo, "}\n");
  shift_fprintf (--level, fo, "}\n");
  return 0;
  return 0;
}
}
 
 
/* Generates .c file header */
/* Generates .c file header */
static int generate_header (FILE *fo)
static int generate_header (FILE *fo)
{
{
  fprintf (fo, "/* execgen.c -- Automatically generated decoder\n");
  fprintf (fo, "/* execgen.c -- Automatically generated decoder\n");
  fprintf (fo, "\n");
  fprintf (fo, "\n");
  fprintf (fo, "   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
  fprintf (fo, "   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
  fprintf (fo, "   Copyright (C) 2008 Embecosm Limited\n");
  fprintf (fo, "   Copyright (C) 2008 Embecosm Limited\n");
  fprintf (fo, "\n");
  fprintf (fo, "\n");
  fprintf (fo, "   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>\n");
  fprintf (fo, "   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>\n");
  fprintf (fo, "\n");
  fprintf (fo, "\n");
  fprintf (fo, "   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.\n");
  fprintf (fo, "   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.\n");
  fprintf (fo, "\n");
  fprintf (fo, "\n");
  fprintf (fo, "   This program is free software; you can redistribute it and/or modify it\n");
  fprintf (fo, "   This program is free software; you can redistribute it and/or modify it\n");
  fprintf (fo, "   under the terms of the GNU General Public License as published by the Free\n");
  fprintf (fo, "   under the terms of the GNU General Public License as published by the Free\n");
  fprintf (fo, "   Software Foundation; either version 3 of the License, or (at your option)\n");
  fprintf (fo, "   Software Foundation; either version 3 of the License, or (at your option)\n");
  fprintf (fo, "   any later version.\n");
  fprintf (fo, "   any later version.\n");
  fprintf (fo, "\n");
  fprintf (fo, "\n");
  fprintf (fo, "   This program is distributed in the hope that it will be useful, but WITHOUT\n");
  fprintf (fo, "   This program is distributed in the hope that it will be useful, but WITHOUT\n");
  fprintf (fo, "   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n");
  fprintf (fo, "   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n");
  fprintf (fo, "   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\n");
  fprintf (fo, "   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\n");
  fprintf (fo, "   more details.\n");
  fprintf (fo, "   more details.\n");
  fprintf (fo, "\n");
  fprintf (fo, "\n");
  fprintf (fo, "   You should have received a copy of the GNU General Public License along\n");
  fprintf (fo, "   You should have received a copy of the GNU General Public License along\n");
  fprintf (fo, "   with this program.  If not, see <http://www.gnu.org/licenses/>.  */\n");
  fprintf (fo, "   with this program.  If not, see <http://www.gnu.org/licenses/>.  */\n");
  fprintf (fo, "\n");
  fprintf (fo, "\n");
  fprintf (fo, "/* This program is commented throughout in a fashion suitable for processing\n");
  fprintf (fo, "/* This program is commented throughout in a fashion suitable for processing\n");
  fprintf (fo, "   with Doxygen. */\n");
  fprintf (fo, "   with Doxygen. */\n");
  fprintf (fo, "\n");
  fprintf (fo, "\n");
 
 
  fprintf (fo, "/* This file was automatically generated by generate (see\n");
  fprintf (fo, "/* This file was automatically generated by generate (see\n");
  fprintf (fo, "   cpu/or32/generate.c) */\n\n");
  fprintf (fo, "   cpu/or32/generate.c) */\n\n");
  fprintf (fo, "#include <math.h>\n\n");
  fprintf (fo, "#include <math.h>\n\n");
  fprintf (fo, "#include <stdint.h>\n\n");
  fprintf (fo, "#include <stdint.h>\n\n");
  fprintf (fo, "typedef union {\n\tfloat fval;\n\tuint32_t hval;\n} FLOAT;\n\n");
  fprintf (fo, "typedef union {\n\tfloat fval;\n\tuint32_t hval;\n} FLOAT;\n\n");
  fprintf (fo, "static void decode_execute (struct iqueue_entry *current)\n{\n");
  fprintf (fo, "static void decode_execute (struct iqueue_entry *current)\n{\n");
  fprintf (fo, "  uint32_t insn = current->insn;\n");
  fprintf (fo, "  uint32_t insn = current->insn;\n");
  out_lines = 5;
  out_lines = 5;
  return 0;
  return 0;
}
}
 
 
/* Generates .c file footer */
/* Generates .c file footer */
static int generate_footer (FILE *fo)
static int generate_footer (FILE *fo)
{
{
  fprintf (fo, "}\n");
  fprintf (fo, "}\n");
  return 0;
  return 0;
}
}
 
 
/* Decodes all instructions and generates code for that.  This function
/* Decodes all instructions and generates code for that.  This function
   is similar to insn_decode, except it decodes all instructions.
   is similar to insn_decode, except it decodes all instructions.
 
 
   JPB: Added code to generate an illegal instruction exception for invalid
   JPB: Added code to generate an illegal instruction exception for invalid
   instructions. */
   instructions. */
static int generate_body (FILE *fo, unsigned long *a, unsigned long cur_mask, int level)
static int generate_body (FILE *fo, unsigned long *a, unsigned long cur_mask, int level)
{
{
  unsigned long shift = *a;
  unsigned long shift = *a;
  unsigned long mask;
  unsigned long mask;
  int i;
  int i;
  int prev_inv = 0;
  int prev_inv = 0;
 
 
  if (!(*a & LEAF_FLAG)) {
  if (!(*a & LEAF_FLAG)) {
    shift = *a++;
    shift = *a++;
    mask = *a++;
    mask = *a++;
    shift_fprintf (level, fo, "switch((insn >> %i) & 0x%x) {\n", shift,
    shift_fprintf (level, fo, "switch((insn >> %i) & 0x%x) {\n", shift,
                   mask);
                   mask);
    for (i = 0; i <= mask; i++, a++) {
    for (i = 0; i <= mask; i++, a++) {
      if (!*a) {
      if (!*a) {
        shift_fprintf (level, fo, "case 0x%x:\n", i);
        shift_fprintf (level, fo, "case 0x%x:\n", i);
        prev_inv = 1;
        prev_inv = 1;
      } else {
      } else {
        if(prev_inv) {
        if(prev_inv) {
          shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
          shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
          shift_fprintf (level--, fo, "break;\n");
          shift_fprintf (level--, fo, "break;\n");
        }
        }
        shift_fprintf (level, fo, "case 0x%x:\n", i);
        shift_fprintf (level, fo, "case 0x%x:\n", i);
        generate_body (fo, automata + *a, cur_mask | (mask << shift), ++level);
        generate_body (fo, automata + *a, cur_mask | (mask << shift), ++level);
        shift_fprintf (level--, fo, "break;\n");
        shift_fprintf (level--, fo, "break;\n");
        prev_inv = 0;
        prev_inv = 0;
      }
      }
    }
    }
    if (prev_inv) {
    if (prev_inv) {
      shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
      shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
      shift_fprintf (level, fo,
      shift_fprintf (level, fo,
                     "except_handle (EXCEPT_ILLEGAL, cpu_state.pc);\n");
                     "except_handle (EXCEPT_ILLEGAL, cpu_state.pc);\n");
      shift_fprintf (level--, fo, "break;\n");
      shift_fprintf (level--, fo, "break;\n");
    }
    }
    shift_fprintf (level, fo, "}\n");
    shift_fprintf (level, fo, "}\n");
  } else {
  } else {
    i = *a & ~LEAF_FLAG;
    i = *a & ~LEAF_FLAG;
 
 
    /* Final check - do we have direct match?
    /* Final check - do we have direct match?
       (based on or32_opcodes this should be the only possibility,
       (based on or32_opcodes this should be the only possibility,
       but in case of invalid/missing instruction we must perform a check)  */
       but in case of invalid/missing instruction we must perform a check)  */
 
 
    if (ti[i].insn_mask != cur_mask) {
    if (ti[i].insn_mask != cur_mask) {
      shift_fprintf (level, fo, "/* Not unique: real mask %08lx and current mask %08lx differ - do final check */\n", ti[i].insn_mask, cur_mask);
      shift_fprintf (level, fo, "/* Not unique: real mask %08lx and current mask %08lx differ - do final check */\n", ti[i].insn_mask, cur_mask);
      shift_fprintf (level++, fo, "if((insn & 0x%x) == 0x%x) {\n",
      shift_fprintf (level++, fo, "if((insn & 0x%x) == 0x%x) {\n",
                     ti[i].insn_mask, ti[i].insn);
                     ti[i].insn_mask, ti[i].insn);
    }
    }
    shift_fprintf (level, fo, "/* Instruction: %s */\n", or32_opcodes[i].name);
    shift_fprintf (level, fo, "/* Instruction: %s */\n", or32_opcodes[i].name);
 
 
    output_call (fo, i, level);
    output_call (fo, i, level);
 
 
    if (ti[i].insn_mask != cur_mask) {
    if (ti[i].insn_mask != cur_mask) {
      shift_fprintf (--level, fo, "} else {\n");
      shift_fprintf (--level, fo, "} else {\n");
      shift_fprintf (++level, fo, "/* Invalid insn */\n");
      shift_fprintf (++level, fo, "/* Invalid insn */\n");
      output_call (fo, -1, level);
      output_call (fo, -1, level);
      shift_fprintf (--level, fo, "}\n");
      shift_fprintf (--level, fo, "}\n");
    }
    }
  }
  }
  return 0;
  return 0;
}
}
 
 
/* Main function; it takes two parameters:
/* Main function; it takes two parameters:
   input_file(possibly insnset.c) output_file(possibly execgen.c)*/
   input_file(possibly insnset.c) output_file(possibly execgen.c)*/
int main (int argc, char *argv[])
int main (int argc, char *argv[])
{
{
  FILE *fo;
  FILE *fo;
 
 
  if (argc != 3) {
  if (argc != 3) {
    fprintf (stderr, "USAGE: generate input_file(possibly insnset.c) output_file(possibly execgen.c)\n");
    fprintf (stderr, "USAGE: generate input_file(possibly insnset.c) output_file(possibly execgen.c)\n");
    exit (-1);
    exit (-1);
  }
  }
 
 
  in_file = argv[1];
  in_file = argv[1];
  out_file = argv[2];
  out_file = argv[2];
  if (!(fo = fopen (argv[2], "wt+"))) {
  if (!(fo = fopen (argv[2], "wt+"))) {
    fprintf (stderr, "Cannot create '%s'.\n", argv[2]);
    fprintf (stderr, "Cannot create '%s'.\n", argv[2]);
    exit (1);
    exit (1);
  }
  }
 
 
  build_automata ();
  build_automata (0);
  if (generate_header (fo)) {
  if (generate_header (fo)) {
    fprintf (stderr, "generate_header\n");
    fprintf (stderr, "generate_header\n");
    return 1;
    return 1;
  }
  }
 
 
  if (generate_body (fo, automata, 0, 1)) {
  if (generate_body (fo, automata, 0, 1)) {
    fprintf (stderr, "generate_body\n");
    fprintf (stderr, "generate_body\n");
    return 1;
    return 1;
  }
  }
 
 
  if (generate_footer (fo)) {
  if (generate_footer (fo)) {
    fprintf (stderr, "generate_footer\n");
    fprintf (stderr, "generate_footer\n");
    return 1;
    return 1;
  }
  }
 
 
  fclose (fo);
  fclose (fo);
  destruct_automata ();
  destruct_automata ();
  return 0;
  return 0;
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.