ia64-gen.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,504 行 · 第 1/5 页

C
2,504
字号
/* ia64-gen.c -- Generate a shrunk set of opcode tables   Copyright 1999, 2000 Free Software Foundation, Inc.   Written by Bob Manson, Cygnus Solutions, <manson@cygnus.com>   This file is part of GDB, GAS, and the GNU binutils.   GDB, GAS, and the GNU binutils are free software; you can redistribute   them and/or modify them under the terms of the GNU General Public   License as published by the Free Software Foundation; either version   2, or (at your option) any later version.   GDB, GAS, and the GNU binutils are distributed in the hope that they   will be useful, but WITHOUT ANY WARRANTY; without even the implied   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See   the GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this file; see the file COPYING.  If not, write to the   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA   02111-1307, USA.  *//* While the ia64-opc-* set of opcode tables are easy to maintain,   they waste a tremendous amount of space.  ia64-gen rearranges the   instructions into a directed acyclic graph (DAG) of instruction opcodes and    their possible completers, as well as compacting the set of strings used.     The disassembler table consists of a state machine that does   branching based on the bits of the opcode being disassembled.  The   state encodings have been chosen to minimize the amount of space   required.     The resource table is constructed based on some text dependency tables,    which are also easier to maintain than the final representation.*/#include <stdio.h>#include <ctype.h>#include "ansidecl.h"#include "libiberty.h"#include "sysdep.h"#include "ia64-opc.h"#include "ia64-opc-a.c"#include "ia64-opc-i.c"#include "ia64-opc-m.c"#include "ia64-opc-b.c"#include "ia64-opc-f.c"#include "ia64-opc-x.c"#include "ia64-opc-d.c"int debug = 0;#define tmalloc(X) (X *) xmalloc (sizeof (X))/* The main opcode table entry.  Each entry is a unique combination of   name and flags (no two entries in the table compare as being equal   via opcodes_eq). */struct main_entry{  /* The base name of this opcode.  The names of its completers are     appended to it to generate the full instruction name. */  struct string_entry *name;  /* The base opcode entry.  Which one to use is a fairly arbitrary choice;     it uses the first one passed to add_opcode_entry. */  struct ia64_opcode *opcode;  /* The list of completers that can be applied to this opcode. */  struct completer_entry *completers;  /* Next entry in the chain. */  struct main_entry *next;  /* Index in the  main table. */  int main_index;} *maintable, **ordered_table;int otlen = 0;int ottotlen = 0;int opcode_count = 0;/* The set of possible completers for an opcode. */struct completer_entry{  /* This entry's index in the ia64_completer_table[] array. */  int num;  /* The name of the completer. */  struct string_entry *name;  /* This entry's parent. */  struct completer_entry *parent;  /* Set if this is a terminal completer (occurs at the end of an     opcode). */  int is_terminal;  /* An alternative completer. */  struct completer_entry *alternative;  /* Additional completers that can be appended to this one.  */  struct completer_entry *addl_entries;  /* Before compute_completer_bits () is invoked, this contains the actual     instruction opcode for this combination of opcode and completers.     Afterwards, it contains those bits that are different from its     parent opcode. */  ia64_insn bits;  /* Bits set to 1 correspond to those bits in this completer's opcode     that are different from its parent completer's opcode (or from     the base opcode if the entry is the root of the opcode's completer     list).  This field is filled in by compute_completer_bits (). */  ia64_insn mask;  /* Index into the opcode dependency list, or -1 if none. */  int dependencies;  /* Remember the order encountered in the opcode tables.  */  int order;};/* One entry in the disassembler name table. */struct disent{  /* The index into the ia64_name_dis array for this entry. */  int ournum;  /* The index into the main_table[] array. */  int insn;  /* The disassmbly priority of this entry. */  int priority;  /* The completer_index value for this entry. */  int completer_index;  /* How many other entries share this decode. */  int nextcnt;  /* The next entry sharing the same decode. */  struct disent *nexte;  /* The next entry in the name list. */  struct disent *next_ent;} *disinsntable = NULL;/* A state machine that will eventually be used to generate the   disassembler table. */struct bittree{  struct disent *disent;  struct bittree *bits[3]; /* 0, 1, and X (don't care) */  int bits_to_skip;  int skip_flag;} *bittree;/* The string table contains all opcodes and completers sorted in   alphabetical order.  *//* One entry in the string table. */struct string_entry {  /* The index in the ia64_strings[] array for this entry. */  int num;  /* And the string. */  char *s;} **string_table = NULL;int strtablen = 0;int strtabtotlen = 0;/* resource dependency entries */struct rdep{  char *name;                       /* resource name */  unsigned     mode:2,                         /* RAW, WAW, or WAR */    semantics:3;                    /* dependency semantics */  char *extra;                      /* additional semantics info */  int nchks;                     int total_chks;                   /* total #of terminal insns */  int *chks;                        /* insn classes which read (RAW), write                                       (WAW), or write (WAR) this rsrc */  int *chknotes;                    /* dependency notes for each class */  int nregs;  int total_regs;                   /* total #of terminal insns */  int *regs;                        /* insn class which write (RAW), write2                                       (WAW), or read (WAR) this rsrc */  int *regnotes;                    /* dependency notes for each class */  int waw_special;                  /* special WAW dependency note */} **rdeps = NULL;static int rdepslen = 0;static int rdepstotlen = 0;/* array of all instruction classes */struct iclass{   char *name;                       /* instruction class name */  int is_class;                     /* is a class, not a terminal */  int nsubs;                          int *subs;                        /* other classes within this class */  int nxsubs;                         int xsubs[4];                     /* exclusions */  char *comment;                    /* optional comment */  int note;                         /* optional note */  int terminal_resolved;            /* did we match this with anything? */  int orphan;                       /* detect class orphans */} **ics = NULL;static int iclen = 0;static int ictotlen = 0;/* an opcode dependency (chk/reg pair of dependency lists) */struct opdep{  int chk;                          /* index into dlists */  int reg;                          /* index into dlists */} **opdeps;static int opdeplen = 0;static int opdeptotlen = 0;/* a generic list of dependencies w/notes encoded.  these may be shared. */struct deplist{  int len;  unsigned short *deps;} **dlists;static int dlistlen = 0;static int dlisttotlen = 0;/* add NAME to the resource table, where TYPE is RAW or WAW */static struct rdep *insert_resource (const char *name, enum ia64_dependency_mode type){  if (rdepslen == rdepstotlen)    {      rdepstotlen += 20;      rdeps = (struct rdep **)        xrealloc (rdeps, sizeof(struct rdep **) * rdepstotlen);    }  rdeps[rdepslen] = tmalloc(struct rdep);  memset((void *)rdeps[rdepslen], 0, sizeof(struct rdep));  rdeps[rdepslen]->name = xstrdup (name);  rdeps[rdepslen]->mode = type;  rdeps[rdepslen]->waw_special = 0;    return rdeps[rdepslen++];}/* are the lists of dependency indexes equivalent? */static intdeplist_equals (struct deplist *d1, struct deplist *d2){  int i;  if (d1->len != d2->len)    return 0;  for (i=0;i < d1->len;i++)    {      if (d1->deps[i] != d2->deps[i])        return 0;    }  return 1;}/* add the list of dependencies to the list of dependency lists */static shortinsert_deplist(int count, unsigned short *deps){  /* sort the list, then see if an equivalent list exists already.     this results in a much smaller set of dependency lists   */  struct deplist *list;  char set[0x10000];  int i;  memset ((void *)set, 0, sizeof(set));  for (i=0;i < count;i++)    set[deps[i]] = 1;  count = 0;  for (i=0;i < (int)sizeof(set);i++)    if (set[i])      ++count;  list = tmalloc(struct deplist);  list->len = count;  list->deps = (unsigned short *)malloc (sizeof(unsigned short) * count);  for (i=0, count=0;i < (int)sizeof(set);i++)    {      if (set[i])        {          list->deps[count++] = i;        }    }  /* does this list exist already? */  for (i=0;i < dlistlen;i++)    {      if (deplist_equals (list, dlists[i]))        {          free (list->deps);          free (list);          return i;        }    }  if (dlistlen == dlisttotlen)    {      dlisttotlen += 20;      dlists = (struct deplist **)        xrealloc (dlists, sizeof(struct deplist **) * dlisttotlen);    }  dlists[dlistlen] = list;  return dlistlen++;}/* add the given pair of dependency lists to the opcode dependency list */static shortinsert_dependencies (int nchks, unsigned short *chks,                      int nregs, unsigned short *regs){  struct opdep *pair;  int i;  int regind = -1;  int chkind = -1;  if (nregs > 0)    regind = insert_deplist (nregs, regs);  if (nchks > 0)    chkind = insert_deplist (nchks, chks);  for (i=0;i < opdeplen;i++)    {      if (opdeps[i]->chk == chkind           && opdeps[i]->reg == regind)        return i;    }  pair = tmalloc(struct opdep);  pair->chk = chkind;  pair->reg = regind;    if (opdeplen == opdeptotlen)    {      opdeptotlen += 20;      opdeps = (struct opdep **)        xrealloc (opdeps, sizeof(struct opdep **) * opdeptotlen);    }  opdeps[opdeplen] = pair;  return opdeplen++;}static void mark_used (struct iclass *ic, int clear_terminals){  int i;  ic->orphan = 0;  if (clear_terminals)    ic->terminal_resolved = 1;  for (i=0;i < ic->nsubs;i++)    {      mark_used (ics[ic->subs[i]], clear_terminals);    }  for (i=0;i < ic->nxsubs;i++)    {      mark_used (ics[ic->xsubs[i]], clear_terminals);    }}/* look up an instruction class; if CREATE make a new one if none found;   returns the index into the insn class array */static intfetch_insn_class(const char *full_name, int create){  char *name;  char *notestr;  char *xsect;  char *comment;  int i, note = 0;  int ind;  int is_class = 0;  if (strncmp (full_name, "IC:", 3) == 0)    {      name = xstrdup (full_name + 3);      is_class = 1;    }  else    name = xstrdup (full_name);  if ((xsect = strchr(name, '\\')) != NULL)    is_class = 1;  if ((comment = strchr(name, '[')) != NULL)    is_class = 1;  if ((notestr = strchr(name, '+')) != NULL)    is_class = 1;  /* If it is a composite class, then ignore comments and notes that come after     the '\\', since they don't apply to the part we are decoding now.  */  if (xsect)    {      if (comment > xsect)	comment = 0;      if (notestr > xsect)	notestr = 0;    }  if (notestr)    {      char *nextnotestr;      note = atoi (notestr + 1);      if ((nextnotestr = strchr (notestr + 1, '+')) != NULL)        {          if (strcmp (notestr, "+1+13") == 0)            note = 13;          else if (!xsect || nextnotestr < xsect)            fprintf (stderr, "Warning: multiple note %s not handled\n",                     notestr);        }    }  /* If it's a composite class, leave the notes and comments in place so that     we have a unique name for the composite class.  Otherwise, we remove     them.  */  if (!xsect)    {      if (notestr)        *notestr = 0;      if (comment)        *comment = 0;    }  for (i=0;i < iclen;i++)    if (strcmp(name, ics[i]->name) == 0        && ((comment == NULL && ics[i]->comment == NULL)            || (comment != NULL && ics[i]->comment != NULL                && strncmp (ics[i]->comment, comment,                             strlen (ics[i]->comment)) == 0))        && note == ics[i]->note)      return i;  if (!create)    return -1;  /* doesn't exist, so make a new one */  if (iclen == ictotlen)    {      ictotlen += 20;      ics = (struct iclass **)        xrealloc(ics, (ictotlen)*sizeof(struct iclass *));    }  ind = iclen++;  ics[ind] = tmalloc(struct iclass);  memset((void *)ics[ind], 0, sizeof(struct iclass));  ics[ind]->name = xstrdup(name);  ics[ind]->is_class = is_class;  ics[ind]->orphan = 1;  if (comment)    {      ics[ind]->comment = xstrdup (comment + 1);      ics[ind]->comment[strlen(ics[ind]->comment)-1] = 0;    }  if (notestr)    ics[ind]->note = note;  /* if it's a composite class, there's a comment or note, look for an     existing class or terminal with the same name. */   if ((xsect || comment || notestr) && is_class)    {      /* First, populate with the class we're based on.  */      char *subname = name;      if (xsect)        *xsect = 0;      else if (comment)        *comment = 0;      else if (notestr)        *notestr = 0;      ics[ind]->nsubs = 1;      ics[ind]->subs = tmalloc(int);      ics[ind]->subs[0] = fetch_insn_class (subname, 1);;    }  while (xsect)    {      char *subname = xsect + 1;      xsect = strchr (subname, '\\');      if (xsect)        *xsect = 0;      ics[ind]->xsubs[ics[ind]->nxsubs] = fetch_insn_class (subname,1);      ics[ind]->nxsubs++;    }  free (name);  return ind;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?