⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ia64-gen.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
/* ia64-gen.c -- Generate a shrunk set of opcode tables   Copyright 1999, 2000, 2001, 2002, 2004, 2005, 2006   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, 51 Franklin Street - Fifth Floor, Boston, MA   02110-1301, 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 <stdarg.h>#include <errno.h>#include "ansidecl.h"#include "libiberty.h"#include "safe-ctype.h"#include "sysdep.h"#include "getopt.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"#include <libintl.h>#define _(String) gettext (String)/* This is a copy of fprintf_vma from bfd/bfd-in2.h.  We have to use this   always, because we might be compiled without BFD64 defined, if configured   for a 32-bit target and --enable-targets=all is used.  This will work for   both 32-bit and 64-bit hosts.  */#define _opcode_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))#define _opcode_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))#define opcode_fprintf_vma(s,x) \  fprintf ((s), "%08lx%08lx", _opcode_int64_high (x), _opcode_int64_low (x))const char * program_name = NULL;int debug = 0;#define NELEMS(a) (sizeof (a) / sizeof ((a)[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;static void fail (const char *, ...) ATTRIBUTE_PRINTF_1;static void warn (const char *, ...) ATTRIBUTE_PRINTF_1;static struct rdep * insert_resource (const char *, enum ia64_dependency_mode);static int  deplist_equals (struct deplist *, struct deplist *);static short insert_deplist (int, unsigned short *);static short insert_dependencies (int, unsigned short *, int, unsigned short *);static void  mark_used (struct iclass *, int);static int  fetch_insn_class (const char *, int);static int  sub_compare (const void *, const void *);static void load_insn_classes (void);static void parse_resource_users (const char *, int **, int *, int **);static int  parse_semantics (char *);static void add_dep (const char *, const char *, const char *, int, int, char *, int);static void load_depfile (const char *, enum ia64_dependency_mode);static void load_dependencies (void);static int  irf_operand (int, const char *);static int  in_iclass_mov_x (struct ia64_opcode *, struct iclass *, const char *, const char *);static int  in_iclass (struct ia64_opcode *, struct iclass *, const char *, const char *, int *);static int  lookup_regindex (const char *, int);static int  lookup_specifier (const char *);static void print_dependency_table (void);static struct string_entry * insert_string (char *);static void gen_dis_table (struct bittree *);static void print_dis_table (void);static void generate_disassembler (void);static void print_string_table (void);static int  completer_entries_eq (struct completer_entry *, struct completer_entry *);static struct completer_entry * insert_gclist (struct completer_entry *);static int  get_prefix_len (const char *);static void compute_completer_bits (struct main_entry *, struct completer_entry *);static void collapse_redundant_completers (void);static int  insert_opcode_dependencies (struct ia64_opcode *, struct completer_entry *);static void insert_completer_entry (struct ia64_opcode *, struct main_entry *, int);static void print_completer_entry (struct completer_entry *);static void print_completer_table (void);static int  opcodes_eq (struct ia64_opcode *, struct ia64_opcode *);static void add_opcode_entry (struct ia64_opcode *);static void print_main_table (void);static void shrink (struct ia64_opcode *);static void print_version (void);static void usage (FILE *, int);static void finish_distable (void);static void insert_bit_table_ent (struct bittree *, int, ia64_insn, ia64_insn, int, int, int);static void add_dis_entry (struct bittree *, ia64_insn, ia64_insn, int, struct completer_entry *, int);static void compact_distree (struct bittree *);static struct bittree * make_bittree_entry (void);static struct disent * add_dis_table_ent (struct disent *, int, int, int);static voidfail (const char *message, ...){  va_list args;    va_start (args, message);  fprintf (stderr, _("%s: Error: "), program_name);  vfprintf (stderr, message, args);  va_end (args);  xexit (1);}static voidwarn (const char *message, ...){  va_list args;  va_start (args, message);  fprintf (stderr, _("%s: Warning: "), program_name);  vfprintf (stderr, message, args);  va_end (args);}/* 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;

⌨️ 快捷键说明

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