Back to index

cell-binutils  2.17cvs20070401
ia64-gen.c
Go to the documentation of this file.
00001 /* ia64-gen.c -- Generate a shrunk set of opcode tables
00002    Copyright 1999, 2000, 2001, 2002, 2004, 2005, 2006
00003    Free Software Foundation, Inc.
00004    Written by Bob Manson, Cygnus Solutions, <manson@cygnus.com>
00005 
00006    This file is part of GDB, GAS, and the GNU binutils.
00007 
00008    GDB, GAS, and the GNU binutils are free software; you can redistribute
00009    them and/or modify them under the terms of the GNU General Public
00010    License as published by the Free Software Foundation; either version
00011    2, or (at your option) any later version.
00012 
00013    GDB, GAS, and the GNU binutils are distributed in the hope that they
00014    will be useful, but WITHOUT ANY WARRANTY; without even the implied
00015    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
00016    the GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this file; see the file COPYING.  If not, write to the
00020    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 /* While the ia64-opc-* set of opcode tables are easy to maintain,
00024    they waste a tremendous amount of space.  ia64-gen rearranges the
00025    instructions into a directed acyclic graph (DAG) of instruction opcodes and 
00026    their possible completers, as well as compacting the set of strings used.  
00027 
00028    The disassembler table consists of a state machine that does
00029    branching based on the bits of the opcode being disassembled.  The
00030    state encodings have been chosen to minimize the amount of space
00031    required.  
00032 
00033    The resource table is constructed based on some text dependency tables, 
00034    which are also easier to maintain than the final representation.  */
00035 
00036 #include <stdio.h>
00037 #include <stdarg.h>
00038 #include <errno.h>
00039 
00040 #include "ansidecl.h"
00041 #include "libiberty.h"
00042 #include "safe-ctype.h"
00043 #include "sysdep.h"
00044 #include "getopt.h"
00045 #include "ia64-opc.h"
00046 #include "ia64-opc-a.c"
00047 #include "ia64-opc-i.c"
00048 #include "ia64-opc-m.c"
00049 #include "ia64-opc-b.c"
00050 #include "ia64-opc-f.c"
00051 #include "ia64-opc-x.c"
00052 #include "ia64-opc-d.c"
00053 
00054 #include <libintl.h>
00055 #define _(String) gettext (String)
00056 
00057 /* This is a copy of fprintf_vma from bfd/bfd-in2.h.  We have to use this
00058    always, because we might be compiled without BFD64 defined, if configured
00059    for a 32-bit target and --enable-targets=all is used.  This will work for
00060    both 32-bit and 64-bit hosts.  */
00061 #define _opcode_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
00062 #define _opcode_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
00063 #define opcode_fprintf_vma(s,x) \
00064   fprintf ((s), "%08lx%08lx", _opcode_int64_high (x), _opcode_int64_low (x))
00065 
00066 const char * program_name = NULL;
00067 int debug = 0;
00068 
00069 #define NELEMS(a) (sizeof (a) / sizeof ((a)[0]))
00070 #define tmalloc(X) (X *) xmalloc (sizeof (X))
00071 
00072 /* The main opcode table entry.  Each entry is a unique combination of
00073    name and flags (no two entries in the table compare as being equal
00074    via opcodes_eq).  */
00075 struct main_entry
00076 {
00077   /* The base name of this opcode.  The names of its completers are
00078      appended to it to generate the full instruction name.  */
00079   struct string_entry *name;
00080   /* The base opcode entry.  Which one to use is a fairly arbitrary choice;
00081      it uses the first one passed to add_opcode_entry.  */
00082   struct ia64_opcode *opcode;
00083   /* The list of completers that can be applied to this opcode.  */
00084   struct completer_entry *completers;
00085   /* Next entry in the chain.  */
00086   struct main_entry *next;
00087   /* Index in the  main table.  */
00088   int main_index;
00089 } *maintable, **ordered_table;
00090 
00091 int otlen = 0;
00092 int ottotlen = 0;
00093 int opcode_count = 0;
00094 
00095 /* The set of possible completers for an opcode.  */
00096 struct completer_entry
00097 {
00098   /* This entry's index in the ia64_completer_table[] array.  */
00099   int num;
00100 
00101   /* The name of the completer.  */
00102   struct string_entry *name;
00103 
00104   /* This entry's parent.  */
00105   struct completer_entry *parent;
00106 
00107   /* Set if this is a terminal completer (occurs at the end of an
00108      opcode).  */
00109   int is_terminal;
00110 
00111   /* An alternative completer.  */
00112   struct completer_entry *alternative;
00113 
00114   /* Additional completers that can be appended to this one.  */
00115   struct completer_entry *addl_entries;
00116 
00117   /* Before compute_completer_bits () is invoked, this contains the actual
00118      instruction opcode for this combination of opcode and completers.
00119      Afterwards, it contains those bits that are different from its
00120      parent opcode.  */
00121   ia64_insn bits;
00122 
00123   /* Bits set to 1 correspond to those bits in this completer's opcode
00124      that are different from its parent completer's opcode (or from
00125      the base opcode if the entry is the root of the opcode's completer
00126      list).  This field is filled in by compute_completer_bits ().  */
00127   ia64_insn mask;
00128 
00129   /* Index into the opcode dependency list, or -1 if none.  */
00130   int dependencies;
00131 
00132   /* Remember the order encountered in the opcode tables.  */
00133   int order;
00134 };
00135 
00136 /* One entry in the disassembler name table.  */
00137 struct disent
00138 {
00139   /* The index into the ia64_name_dis array for this entry.  */
00140   int ournum;
00141 
00142   /* The index into the main_table[] array.  */
00143   int insn;
00144 
00145   /* The disassmbly priority of this entry.  */
00146   int priority;
00147 
00148   /* The completer_index value for this entry.  */
00149   int completer_index;
00150 
00151   /* How many other entries share this decode.  */
00152   int nextcnt;
00153 
00154   /* The next entry sharing the same decode.  */
00155   struct disent *nexte;
00156 
00157   /* The next entry in the name list.  */
00158   struct disent *next_ent;
00159 } *disinsntable = NULL;
00160 
00161 /* A state machine that will eventually be used to generate the
00162    disassembler table.  */
00163 struct bittree
00164 {
00165   struct disent *disent;
00166   struct bittree *bits[3]; /* 0, 1, and X (don't care).  */
00167   int bits_to_skip;
00168   int skip_flag;
00169 } *bittree;
00170 
00171 /* The string table contains all opcodes and completers sorted in
00172    alphabetical order.  */
00173 
00174 /* One entry in the string table.  */
00175 struct string_entry 
00176 {
00177   /* The index in the ia64_strings[] array for this entry.  */
00178   int num;
00179   /* And the string.  */
00180   char *s;
00181 } **string_table = NULL;
00182 
00183 int strtablen = 0;
00184 int strtabtotlen = 0;
00185 
00186 
00187 /* Resource dependency entries.  */
00188 struct rdep
00189 {
00190   char *name;                       /* Resource name.  */
00191   unsigned 
00192     mode:2,                         /* RAW, WAW, or WAR.  */
00193     semantics:3;                    /* Dependency semantics.  */
00194   char *extra;                      /* Additional semantics info.  */
00195   int nchks;                   
00196   int total_chks;                   /* Total #of terminal insns.  */
00197   int *chks;                        /* Insn classes which read (RAW), write
00198                                        (WAW), or write (WAR) this rsrc.  */
00199   int *chknotes;                    /* Dependency notes for each class.  */
00200   int nregs;
00201   int total_regs;                   /* Total #of terminal insns.  */
00202   int *regs;                        /* Insn class which write (RAW), write2
00203                                        (WAW), or read (WAR) this rsrc.  */
00204   int *regnotes;                    /* Dependency notes for each class.  */
00205 
00206   int waw_special;                  /* Special WAW dependency note.  */
00207 } **rdeps = NULL;
00208 
00209 static int rdepslen = 0;
00210 static int rdepstotlen = 0;
00211 
00212 /* Array of all instruction classes.  */
00213 struct iclass
00214 { 
00215   char *name;                       /* Instruction class name.  */
00216   int is_class;                     /* Is a class, not a terminal.  */
00217   int nsubs;                        
00218   int *subs;                        /* Other classes within this class.  */
00219   int nxsubs;                       
00220   int xsubs[4];                     /* Exclusions.  */
00221   char *comment;                    /* Optional comment.  */
00222   int note;                         /* Optional note.  */
00223   int terminal_resolved;            /* Did we match this with anything?  */
00224   int orphan;                       /* Detect class orphans.  */
00225 } **ics = NULL;
00226 
00227 static int iclen = 0;
00228 static int ictotlen = 0;
00229 
00230 /* An opcode dependency (chk/reg pair of dependency lists).  */
00231 struct opdep
00232 {
00233   int chk;                          /* index into dlists */
00234   int reg;                          /* index into dlists */
00235 } **opdeps;
00236 
00237 static int opdeplen = 0;
00238 static int opdeptotlen = 0;
00239 
00240 /* A generic list of dependencies w/notes encoded.  These may be shared.  */
00241 struct deplist
00242 {
00243   int len;
00244   unsigned short *deps;
00245 } **dlists;
00246 
00247 static int dlistlen = 0;
00248 static int dlisttotlen = 0;
00249 
00250 
00251 static void fail (const char *, ...) ATTRIBUTE_PRINTF_1;
00252 static void warn (const char *, ...) ATTRIBUTE_PRINTF_1;
00253 static struct rdep * insert_resource (const char *, enum ia64_dependency_mode);
00254 static int  deplist_equals (struct deplist *, struct deplist *);
00255 static short insert_deplist (int, unsigned short *);
00256 static short insert_dependencies (int, unsigned short *, int, unsigned short *);
00257 static void  mark_used (struct iclass *, int);
00258 static int  fetch_insn_class (const char *, int);
00259 static int  sub_compare (const void *, const void *);
00260 static void load_insn_classes (void);
00261 static void parse_resource_users (const char *, int **, int *, int **);
00262 static int  parse_semantics (char *);
00263 static void add_dep (const char *, const char *, const char *, int, int, char *, int);
00264 static void load_depfile (const char *, enum ia64_dependency_mode);
00265 static void load_dependencies (void);
00266 static int  irf_operand (int, const char *);
00267 static int  in_iclass_mov_x (struct ia64_opcode *, struct iclass *, const char *, const char *);
00268 static int  in_iclass (struct ia64_opcode *, struct iclass *, const char *, const char *, int *);
00269 static int  lookup_regindex (const char *, int);
00270 static int  lookup_specifier (const char *);
00271 static void print_dependency_table (void);
00272 static struct string_entry * insert_string (char *);
00273 static void gen_dis_table (struct bittree *);
00274 static void print_dis_table (void);
00275 static void generate_disassembler (void);
00276 static void print_string_table (void);
00277 static int  completer_entries_eq (struct completer_entry *, struct completer_entry *);
00278 static struct completer_entry * insert_gclist (struct completer_entry *);
00279 static int  get_prefix_len (const char *);
00280 static void compute_completer_bits (struct main_entry *, struct completer_entry *);
00281 static void collapse_redundant_completers (void);
00282 static int  insert_opcode_dependencies (struct ia64_opcode *, struct completer_entry *);
00283 static void insert_completer_entry (struct ia64_opcode *, struct main_entry *, int);
00284 static void print_completer_entry (struct completer_entry *);
00285 static void print_completer_table (void);
00286 static int  opcodes_eq (struct ia64_opcode *, struct ia64_opcode *);
00287 static void add_opcode_entry (struct ia64_opcode *);
00288 static void print_main_table (void);
00289 static void shrink (struct ia64_opcode *);
00290 static void print_version (void);
00291 static void usage (FILE *, int);
00292 static void finish_distable (void);
00293 static void insert_bit_table_ent (struct bittree *, int, ia64_insn, ia64_insn, int, int, int);
00294 static void add_dis_entry (struct bittree *, ia64_insn, ia64_insn, int, struct completer_entry *, int);
00295 static void compact_distree (struct bittree *);
00296 static struct bittree * make_bittree_entry (void);
00297 static struct disent * add_dis_table_ent (struct disent *, int, int, int);
00298 
00299 
00300 static void
00301 fail (const char *message, ...)
00302 {
00303   va_list args;
00304   
00305   va_start (args, message);
00306   fprintf (stderr, _("%s: Error: "), program_name);
00307   vfprintf (stderr, message, args);
00308   va_end (args);
00309   xexit (1);
00310 }
00311 
00312 static void
00313 warn (const char *message, ...)
00314 {
00315   va_list args;
00316 
00317   va_start (args, message);
00318 
00319   fprintf (stderr, _("%s: Warning: "), program_name);
00320   vfprintf (stderr, message, args);
00321   va_end (args);
00322 }
00323 
00324 /* Add NAME to the resource table, where TYPE is RAW or WAW.  */
00325 static struct rdep *
00326 insert_resource (const char *name, enum ia64_dependency_mode type)
00327 {
00328   if (rdepslen == rdepstotlen)
00329     {
00330       rdepstotlen += 20;
00331       rdeps = (struct rdep **)
00332         xrealloc (rdeps, sizeof(struct rdep **) * rdepstotlen);
00333     }
00334   rdeps[rdepslen] = tmalloc(struct rdep);
00335   memset((void *)rdeps[rdepslen], 0, sizeof(struct rdep));
00336   rdeps[rdepslen]->name = xstrdup (name);
00337   rdeps[rdepslen]->mode = type;
00338   rdeps[rdepslen]->waw_special = 0;
00339   
00340   return rdeps[rdepslen++];
00341 }
00342 
00343 /* Are the lists of dependency indexes equivalent?  */
00344 static int
00345 deplist_equals (struct deplist *d1, struct deplist *d2)
00346 {
00347   int i;
00348 
00349   if (d1->len != d2->len)
00350     return 0;
00351 
00352   for (i = 0; i < d1->len; i++)
00353     if (d1->deps[i] != d2->deps[i])
00354       return 0;
00355 
00356   return 1;
00357 }
00358 
00359 /* Add the list of dependencies to the list of dependency lists.  */
00360 static short
00361 insert_deplist (int count, unsigned short *deps)
00362 {
00363   /* Sort the list, then see if an equivalent list exists already.
00364      this results in a much smaller set of dependency lists.  */
00365   struct deplist *list;
00366   char set[0x10000];
00367   int i;
00368 
00369   memset ((void *)set, 0, sizeof (set));
00370   for (i = 0; i < count; i++)
00371     set[deps[i]] = 1;
00372 
00373   count = 0;
00374   for (i = 0; i < (int) sizeof (set); i++)
00375     if (set[i])
00376       ++count;
00377 
00378   list = tmalloc (struct deplist);
00379   list->len = count;
00380   list->deps = (unsigned short *) malloc (sizeof (unsigned short) * count);
00381 
00382   for (i = 0, count = 0; i < (int) sizeof (set); i++)
00383     if (set[i])
00384       list->deps[count++] = i;
00385 
00386   /* Does this list exist already?  */
00387   for (i = 0; i < dlistlen; i++)
00388     if (deplist_equals (list, dlists[i]))
00389       {
00390        free (list->deps);
00391        free (list);
00392        return i;
00393       }
00394 
00395   if (dlistlen == dlisttotlen)
00396     {
00397       dlisttotlen += 20;
00398       dlists = (struct deplist **)
00399         xrealloc (dlists, sizeof(struct deplist **) * dlisttotlen);
00400     }
00401   dlists[dlistlen] = list;
00402 
00403   return dlistlen++;
00404 }
00405 
00406 /* Add the given pair of dependency lists to the opcode dependency list.  */
00407 static short
00408 insert_dependencies (int nchks, unsigned short *chks, 
00409                      int nregs, unsigned short *regs)
00410 {
00411   struct opdep *pair;
00412   int i;
00413   int regind = -1;
00414   int chkind = -1;
00415 
00416   if (nregs > 0)
00417     regind = insert_deplist (nregs, regs);
00418   if (nchks > 0)
00419     chkind = insert_deplist (nchks, chks);
00420 
00421   for (i = 0; i < opdeplen; i++)
00422     if (opdeps[i]->chk == chkind 
00423        && opdeps[i]->reg == regind)
00424       return i;
00425 
00426   pair = tmalloc (struct opdep);
00427   pair->chk = chkind;
00428   pair->reg = regind;
00429   
00430   if (opdeplen == opdeptotlen)
00431     {
00432       opdeptotlen += 20;
00433       opdeps = (struct opdep **)
00434         xrealloc (opdeps, sizeof(struct opdep **) * opdeptotlen);
00435     }
00436   opdeps[opdeplen] = pair;
00437 
00438   return opdeplen++;
00439 }
00440 
00441 static void 
00442 mark_used (struct iclass *ic, int clear_terminals)
00443 {
00444   int i;
00445 
00446   ic->orphan = 0;
00447   if (clear_terminals)
00448     ic->terminal_resolved = 1;
00449 
00450   for (i = 0; i < ic->nsubs; i++)
00451     mark_used (ics[ic->subs[i]], clear_terminals);
00452 
00453   for (i = 0; i < ic->nxsubs; i++)
00454     mark_used (ics[ic->xsubs[i]], clear_terminals);
00455 }
00456 
00457 /* Look up an instruction class; if CREATE make a new one if none found;
00458    returns the index into the insn class array.  */
00459 static int
00460 fetch_insn_class (const char *full_name, int create)
00461 {
00462   char *name;
00463   char *notestr;
00464   char *xsect;
00465   char *comment;
00466   int i, note = 0;
00467   int ind;
00468   int is_class = 0;
00469 
00470   if (CONST_STRNEQ (full_name, "IC:"))
00471     {
00472       name = xstrdup (full_name + 3);
00473       is_class = 1;
00474     }
00475   else
00476     name = xstrdup (full_name);
00477 
00478   if ((xsect = strchr(name, '\\')) != NULL)
00479     is_class = 1;
00480   if ((comment = strchr(name, '[')) != NULL)
00481     is_class = 1;
00482   if ((notestr = strchr(name, '+')) != NULL)
00483     is_class = 1;
00484 
00485   /* If it is a composite class, then ignore comments and notes that come after
00486      the '\\', since they don't apply to the part we are decoding now.  */
00487   if (xsect)
00488     {
00489       if (comment > xsect)
00490        comment = 0;
00491       if (notestr > xsect)
00492        notestr = 0;
00493     }
00494 
00495   if (notestr)
00496     {
00497       char *nextnotestr;
00498 
00499       note = atoi (notestr + 1);
00500       if ((nextnotestr = strchr (notestr + 1, '+')) != NULL)
00501         {
00502           if (strcmp (notestr, "+1+13") == 0)
00503             note = 13;
00504           else if (!xsect || nextnotestr < xsect)
00505             warn (_("multiple note %s not handled\n"), notestr);
00506         }
00507     }
00508 
00509   /* If it's a composite class, leave the notes and comments in place so that
00510      we have a unique name for the composite class.  Otherwise, we remove
00511      them.  */
00512   if (!xsect)
00513     {
00514       if (notestr)
00515         *notestr = 0;
00516       if (comment)
00517         *comment = 0;
00518     }
00519 
00520   for (i = 0; i < iclen; i++)
00521     if (strcmp (name, ics[i]->name) == 0
00522         && ((comment == NULL && ics[i]->comment == NULL)
00523             || (comment != NULL && ics[i]->comment != NULL
00524                 && strncmp (ics[i]->comment, comment, 
00525                             strlen (ics[i]->comment)) == 0))
00526         && note == ics[i]->note)
00527       return i;
00528 
00529   if (!create)
00530     return -1;
00531 
00532   /* Doesn't exist, so make a new one.  */
00533   if (iclen == ictotlen)
00534     {
00535       ictotlen += 20;
00536       ics = (struct iclass **)
00537         xrealloc (ics, (ictotlen) * sizeof (struct iclass *));
00538     }
00539 
00540   ind = iclen++;
00541   ics[ind] = tmalloc (struct iclass);
00542   memset ((void *)ics[ind], 0, sizeof (struct iclass));
00543   ics[ind]->name = xstrdup (name);
00544   ics[ind]->is_class = is_class;
00545   ics[ind]->orphan = 1;
00546 
00547   if (comment)
00548     {
00549       ics[ind]->comment = xstrdup (comment + 1);
00550       ics[ind]->comment[strlen (ics[ind]->comment)-1] = 0;
00551     }
00552 
00553   if (notestr)
00554     ics[ind]->note = note;
00555 
00556   /* If it's a composite class, there's a comment or note, look for an
00557      existing class or terminal with the same name.  */
00558   if ((xsect || comment || notestr) && is_class)
00559     {
00560       /* First, populate with the class we're based on.  */
00561       char *subname = name;
00562 
00563       if (xsect)
00564         *xsect = 0;
00565       else if (comment)
00566         *comment = 0;
00567       else if (notestr)
00568         *notestr = 0;
00569 
00570       ics[ind]->nsubs = 1;
00571       ics[ind]->subs = tmalloc(int);
00572       ics[ind]->subs[0] = fetch_insn_class (subname, 1);;
00573     }
00574 
00575   while (xsect)
00576     {
00577       char *subname = xsect + 1;
00578 
00579       xsect = strchr (subname, '\\');
00580       if (xsect)
00581         *xsect = 0;
00582       ics[ind]->xsubs[ics[ind]->nxsubs] = fetch_insn_class (subname,1);
00583       ics[ind]->nxsubs++;
00584     }
00585   free (name);
00586 
00587   return ind;
00588 }
00589 
00590 /* For sorting a class's sub-class list only; make sure classes appear before
00591    terminals.  */
00592 static int
00593 sub_compare (const void *e1, const void *e2)
00594 {
00595   struct iclass *ic1 = ics[*(int *)e1];
00596   struct iclass *ic2 = ics[*(int *)e2];
00597 
00598   if (ic1->is_class)
00599     {
00600       if (!ic2->is_class)
00601         return -1;
00602     }
00603   else if (ic2->is_class)
00604     return 1;
00605 
00606   return strcmp (ic1->name, ic2->name);
00607 }
00608 
00609 static void
00610 load_insn_classes (void)
00611 {
00612   FILE *fp = fopen ("ia64-ic.tbl", "r");
00613   char buf[2048];
00614 
00615   if (fp == NULL)
00616     fail (_("can't find ia64-ic.tbl for reading\n"));
00617 
00618   /* Discard first line.  */
00619   fgets (buf, sizeof(buf), fp);
00620 
00621   while (!feof (fp))
00622     {
00623       int iclass;
00624       char *name;
00625       char *tmp;
00626       
00627       if (fgets (buf, sizeof (buf), fp) == NULL)
00628         break;
00629       
00630       while (ISSPACE (buf[strlen (buf) - 1]))
00631         buf[strlen (buf) - 1] = '\0';
00632 
00633       name = tmp = buf;
00634       while (*tmp != ';')
00635         {
00636           ++tmp;
00637           if (tmp == buf + sizeof (buf))
00638             abort ();
00639         }
00640       *tmp++ = '\0';
00641 
00642       iclass = fetch_insn_class (name, 1);
00643       ics[iclass]->is_class = 1;
00644 
00645       if (strcmp (name, "none") == 0)
00646         {
00647           ics[iclass]->is_class = 0;
00648           ics[iclass]->terminal_resolved = 1;
00649           continue;
00650         }
00651 
00652       /* For this class, record all sub-classes.  */
00653       while (*tmp)
00654         {
00655           char *subname;
00656           int sub;
00657 
00658           while (*tmp && ISSPACE (*tmp))
00659             {
00660               ++tmp;
00661               if (tmp == buf + sizeof (buf))
00662                 abort ();
00663             }
00664           subname = tmp;
00665           while (*tmp && *tmp != ',')
00666             {
00667               ++tmp;
00668               if (tmp == buf + sizeof (buf))
00669                 abort ();
00670             }
00671           if (*tmp == ',')
00672             *tmp++ = '\0';
00673           
00674           ics[iclass]->subs = (int *)
00675             xrealloc ((void *)ics[iclass]->subs, 
00676                     (ics[iclass]->nsubs + 1) * sizeof (int));
00677 
00678           sub = fetch_insn_class (subname, 1);
00679           ics[iclass]->subs = (int *)
00680             xrealloc (ics[iclass]->subs, (ics[iclass]->nsubs + 1) * sizeof (int));
00681           ics[iclass]->subs[ics[iclass]->nsubs++] = sub;
00682         }
00683 
00684       /* Make sure classes come before terminals.  */
00685       qsort ((void *)ics[iclass]->subs, 
00686              ics[iclass]->nsubs, sizeof(int), sub_compare);
00687     }
00688   fclose (fp);
00689 
00690   if (debug)
00691     printf ("%d classes\n", iclen);
00692 }
00693 
00694 /* Extract the insn classes from the given line.  */
00695 static void
00696 parse_resource_users (ref, usersp, nusersp, notesp)
00697   const char *ref;
00698   int **usersp;
00699   int *nusersp;
00700   int **notesp;
00701 {
00702   int c;
00703   char *line = xstrdup (ref);
00704   char *tmp = line;
00705   int *users = *usersp;
00706   int count = *nusersp;
00707   int *notes = *notesp;
00708 
00709   c = *tmp;
00710   while (c != 0)
00711     {
00712       char *notestr;
00713       int note;
00714       char *xsect;
00715       int iclass;
00716       int create = 0;
00717       char *name;
00718       
00719       while (ISSPACE (*tmp))
00720         ++tmp;
00721       name = tmp;
00722       while (*tmp && *tmp != ',')
00723         ++tmp;
00724       c = *tmp;
00725       *tmp++ = '\0';
00726       
00727       xsect = strchr (name, '\\');
00728       if ((notestr = strstr (name, "+")) != NULL)
00729         {
00730           char *nextnotestr;
00731 
00732           note = atoi (notestr + 1);
00733           if ((nextnotestr = strchr (notestr + 1, '+')) != NULL)
00734             {
00735               /* Note 13 always implies note 1.  */
00736               if (strcmp (notestr, "+1+13") == 0)
00737                 note = 13;
00738               else if (!xsect || nextnotestr < xsect)
00739                 warn (_("multiple note %s not handled\n"), notestr);
00740             }
00741           if (!xsect)
00742             *notestr = '\0';
00743         }
00744       else 
00745         note = 0;
00746 
00747       /* All classes are created when the insn class table is parsed;
00748          Individual instructions might not appear until the dependency tables
00749          are read.  Only create new classes if it's *not* an insn class,
00750          or if it's a composite class (which wouldn't necessarily be in the IC
00751          table).  */
00752       if (! CONST_STRNEQ (name, "IC:") || xsect != NULL)
00753         create = 1;
00754       
00755       iclass = fetch_insn_class (name, create);
00756       if (iclass != -1)
00757         {
00758           users = (int *)
00759             xrealloc ((void *) users,(count + 1) * sizeof (int));
00760           notes = (int *)
00761             xrealloc ((void *) notes,(count + 1) * sizeof (int));
00762           notes[count] = note;
00763           users[count++] = iclass;
00764           mark_used (ics[iclass], 0);
00765         }
00766       else if (debug)
00767        printf("Class %s not found\n", name);
00768     }
00769   /* Update the return values.  */
00770   *usersp = users;
00771   *nusersp = count;
00772   *notesp = notes;
00773 
00774   free (line);
00775 }
00776 
00777 static int
00778 parse_semantics (char *sem)
00779 {
00780   if (strcmp (sem, "none") == 0)
00781     return IA64_DVS_NONE;
00782   else if (strcmp (sem, "implied") == 0)
00783     return IA64_DVS_IMPLIED;
00784   else if (strcmp (sem, "impliedF") == 0)
00785     return IA64_DVS_IMPLIEDF;
00786   else if (strcmp (sem, "data") == 0)
00787     return IA64_DVS_DATA;
00788   else if (strcmp (sem, "instr") == 0)
00789     return IA64_DVS_INSTR;
00790   else if (strcmp (sem, "specific") == 0)
00791     return IA64_DVS_SPECIFIC;
00792   else if (strcmp (sem, "stop") == 0)
00793     return IA64_DVS_STOP;
00794   else 
00795     return IA64_DVS_OTHER;
00796 }
00797 
00798 static void
00799 add_dep (const char *name, const char *chk, const char *reg,
00800          int semantics, int mode, char *extra, int flag)
00801 {
00802   struct rdep *rs;
00803 
00804   rs = insert_resource (name, mode);
00805 
00806   parse_resource_users (chk, &rs->chks, &rs->nchks, &rs->chknotes);
00807   parse_resource_users (reg, &rs->regs, &rs->nregs, &rs->regnotes);
00808 
00809   rs->semantics = semantics;
00810   rs->extra = extra;
00811   rs->waw_special = flag;
00812 }
00813 
00814 static void
00815 load_depfile (const char *filename, enum ia64_dependency_mode mode)
00816 {
00817   FILE *fp = fopen (filename, "r");
00818   char buf[1024];
00819 
00820   if (fp == NULL)
00821     fail (_("can't find %s for reading\n"), filename);
00822 
00823   fgets (buf, sizeof(buf), fp);
00824   while (!feof (fp))
00825     {
00826       char *name, *tmp;
00827       int semantics;
00828       char *extra;
00829       char *regp, *chkp;
00830 
00831       if (fgets (buf, sizeof(buf), fp) == NULL)
00832         break;
00833 
00834       while (ISSPACE (buf[strlen (buf) - 1]))
00835         buf[strlen (buf) - 1] = '\0';
00836 
00837       name = tmp = buf;
00838       while (*tmp != ';')
00839         ++tmp;
00840       *tmp++ = '\0';
00841       
00842       while (ISSPACE (*tmp))
00843         ++tmp;
00844       regp = tmp;
00845       tmp = strchr (tmp, ';');
00846       if (!tmp)
00847         abort ();
00848       *tmp++ = 0;
00849       while (ISSPACE (*tmp))
00850         ++tmp;
00851       chkp = tmp;
00852       tmp = strchr (tmp, ';');
00853       if (!tmp)
00854         abort ();
00855       *tmp++ = 0;
00856       while (ISSPACE (*tmp))
00857         ++tmp;
00858       semantics = parse_semantics (tmp);
00859       extra = semantics == IA64_DVS_OTHER ? xstrdup (tmp) : NULL;
00860 
00861       /* For WAW entries, if the chks and regs differ, we need to enter the
00862          entries in both positions so that the tables will be parsed properly,
00863          without a lot of extra work.  */
00864       if (mode == IA64_DV_WAW && strcmp (regp, chkp) != 0)
00865         {
00866           add_dep (name, chkp, regp, semantics, mode, extra, 0);
00867           add_dep (name, regp, chkp, semantics, mode, extra, 1);
00868         }
00869       else
00870         {
00871           add_dep (name, chkp, regp, semantics, mode, extra, 0);
00872         }
00873     }
00874   fclose (fp);
00875 }
00876 
00877 static void
00878 load_dependencies (void)
00879 {
00880   load_depfile ("ia64-raw.tbl", IA64_DV_RAW);
00881   load_depfile ("ia64-waw.tbl", IA64_DV_WAW);
00882   load_depfile ("ia64-war.tbl", IA64_DV_WAR);
00883 
00884   if (debug)
00885     printf ("%d RAW/WAW/WAR dependencies\n", rdepslen);
00886 }
00887 
00888 /* Is the given operand an indirect register file operand?  */
00889 static int 
00890 irf_operand (int op, const char *field)
00891 {
00892   if (!field)
00893     {
00894       return op == IA64_OPND_RR_R3 || op == IA64_OPND_DBR_R3
00895         || op == IA64_OPND_IBR_R3  || op == IA64_OPND_PKR_R3
00896        || op == IA64_OPND_PMC_R3  || op == IA64_OPND_PMD_R3
00897        || op == IA64_OPND_MSR_R3 || op == IA64_OPND_CPUID_R3;
00898     }
00899   else
00900     {
00901       return ((op == IA64_OPND_RR_R3 && strstr (field, "rr"))
00902               || (op == IA64_OPND_DBR_R3 && strstr (field, "dbr"))
00903               || (op == IA64_OPND_IBR_R3 && strstr (field, "ibr"))
00904               || (op == IA64_OPND_PKR_R3 && strstr (field, "pkr"))
00905               || (op == IA64_OPND_PMC_R3 && strstr (field, "pmc"))
00906               || (op == IA64_OPND_PMD_R3 && strstr (field, "pmd"))
00907               || (op == IA64_OPND_MSR_R3 && strstr (field, "msr"))
00908               || (op == IA64_OPND_CPUID_R3 && strstr (field, "cpuid")));
00909     }
00910 }
00911 
00912 /* Handle mov_ar, mov_br, mov_cr, mov_indirect, mov_ip, mov_pr, mov_psr, and
00913    mov_um insn classes.  */
00914 static int
00915 in_iclass_mov_x (struct ia64_opcode *idesc, struct iclass *ic, 
00916                  const char *format, const char *field)
00917 {
00918   int plain_mov = strcmp (idesc->name, "mov") == 0;
00919 
00920   if (!format)
00921     return 0;
00922 
00923   switch (ic->name[4])
00924     {
00925     default:
00926       abort ();
00927     case 'a':
00928       {
00929         int i = strcmp (idesc->name, "mov.i") == 0;
00930         int m = strcmp (idesc->name, "mov.m") == 0;
00931         int i2627 = i && idesc->operands[0] == IA64_OPND_AR3;
00932         int i28 = i && idesc->operands[1] == IA64_OPND_AR3;
00933         int m2930 = m && idesc->operands[0] == IA64_OPND_AR3;
00934         int m31 = m && idesc->operands[1] == IA64_OPND_AR3;
00935         int pseudo0 = plain_mov && idesc->operands[1] == IA64_OPND_AR3;
00936         int pseudo1 = plain_mov && idesc->operands[0] == IA64_OPND_AR3;
00937 
00938         /* IC:mov ar */
00939         if (i2627)
00940           return strstr (format, "I26") || strstr (format, "I27");
00941         if (i28)
00942           return strstr (format, "I28") != NULL;
00943         if (m2930)
00944           return strstr (format, "M29") || strstr (format, "M30");
00945         if (m31)
00946           return strstr (format, "M31") != NULL;
00947         if (pseudo0 || pseudo1)
00948           return 1;
00949       }
00950       break;
00951     case 'b':
00952       {
00953         int i21 = idesc->operands[0] == IA64_OPND_B1;
00954         int i22 = plain_mov && idesc->operands[1] == IA64_OPND_B2;
00955         if (i22)
00956           return strstr (format, "I22") != NULL;
00957         if (i21)
00958           return strstr (format, "I21") != NULL;
00959       }
00960       break;
00961     case 'c':
00962       {
00963         int m32 = plain_mov && idesc->operands[0] == IA64_OPND_CR3;
00964         int m33 = plain_mov && idesc->operands[1] == IA64_OPND_CR3;
00965         if (m32)
00966           return strstr (format, "M32") != NULL;
00967         if (m33)
00968           return strstr (format, "M33") != NULL;
00969       }
00970       break;
00971     case 'i':
00972       if (ic->name[5] == 'n')
00973         {
00974           int m42 = plain_mov && irf_operand (idesc->operands[0], field);
00975           int m43 = plain_mov && irf_operand (idesc->operands[1], field);
00976           if (m42)
00977             return strstr (format, "M42") != NULL;
00978           if (m43)
00979             return strstr (format, "M43") != NULL;
00980         }
00981       else if (ic->name[5] == 'p')
00982         {
00983           return idesc->operands[1] == IA64_OPND_IP;
00984         }
00985       else
00986         abort ();
00987       break;
00988     case 'p':
00989       if (ic->name[5] == 'r')
00990         {
00991           int i25 = plain_mov && idesc->operands[1] == IA64_OPND_PR;
00992           int i23 = plain_mov && idesc->operands[0] == IA64_OPND_PR;
00993           int i24 = plain_mov && idesc->operands[0] == IA64_OPND_PR_ROT;
00994           if (i23)
00995             return strstr (format, "I23") != NULL;
00996           if (i24)
00997             return strstr (format, "I24") != NULL;
00998           if (i25)
00999             return strstr (format, "I25") != NULL;
01000         }
01001       else if (ic->name[5] == 's')
01002         {
01003           int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_L;
01004           int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR;
01005           if (m35)
01006             return strstr (format, "M35") != NULL;
01007           if (m36)
01008             return strstr (format, "M36") != NULL;
01009         }
01010       else
01011         abort ();
01012       break;
01013     case 'u':
01014       {
01015         int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_UM;
01016         int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR_UM;
01017         if (m35)
01018           return strstr (format, "M35") != NULL;
01019         if (m36)
01020           return strstr (format, "M36") != NULL;
01021       }
01022       break;
01023     }
01024   return 0;
01025 }
01026 
01027 /* Is the given opcode in the given insn class?  */
01028 static int
01029 in_iclass (struct ia64_opcode *idesc, struct iclass *ic, 
01030           const char *format, const char *field, int *notep)
01031 {
01032   int i;
01033   int resolved = 0;
01034 
01035   if (ic->comment)
01036     {
01037       if (CONST_STRNEQ (ic->comment, "Format"))
01038         {
01039           /* Assume that the first format seen is the most restrictive, and
01040              only keep a later one if it looks like it's more restrictive.  */
01041           if (format)
01042             {
01043               if (strlen (ic->comment) < strlen (format))
01044                 {
01045                   warn (_("most recent format '%s'\nappears more restrictive than '%s'\n"),
01046                      ic->comment, format);
01047                   format = ic->comment; 
01048                 }
01049             }
01050           else
01051             format = ic->comment;
01052         }
01053       else if (CONST_STRNEQ (ic->comment, "Field"))
01054         {
01055           if (field)
01056             warn (_("overlapping field %s->%s\n"),
01057                 ic->comment, field);
01058           field = ic->comment;
01059         }
01060     }
01061 
01062   /* An insn class matches anything that is the same followed by completers,
01063      except when the absence and presence of completers constitutes different
01064      instructions.  */
01065   if (ic->nsubs == 0 && ic->nxsubs == 0)
01066     {
01067       int is_mov = CONST_STRNEQ (idesc->name, "mov");
01068       int plain_mov = strcmp (idesc->name, "mov") == 0;
01069       int len = strlen(ic->name);
01070 
01071       resolved = ((strncmp (ic->name, idesc->name, len) == 0)
01072                   && (idesc->name[len] == '\0' 
01073                       || idesc->name[len] == '.'));
01074 
01075       /* All break, nop, and hint variations must match exactly.  */
01076       if (resolved &&
01077           (strcmp (ic->name, "break") == 0
01078            || strcmp (ic->name, "nop") == 0
01079           || strcmp (ic->name, "hint") == 0))
01080         resolved = strcmp (ic->name, idesc->name) == 0;
01081 
01082       /* Assume restrictions in the FORMAT/FIELD negate resolution,
01083          unless specifically allowed by clauses in this block.  */
01084       if (resolved && field)
01085         {
01086           /* Check Field(sf)==sN against opcode sN.  */
01087           if (strstr(field, "(sf)==") != NULL)
01088             {
01089               char *sf;
01090 
01091               if ((sf = strstr (idesc->name, ".s")) != 0)
01092               resolved = strcmp (sf + 1, strstr (field, "==") + 2) == 0;
01093             }
01094           /* Check Field(lftype)==XXX.  */
01095           else if (strstr (field, "(lftype)") != NULL)
01096             {
01097               if (strstr (idesc->name, "fault") != NULL)
01098                 resolved = strstr (field, "fault") != NULL;
01099               else
01100                 resolved = strstr (field, "fault") == NULL;
01101             }
01102           /* Handle Field(ctype)==XXX.  */
01103           else if (strstr (field, "(ctype)") != NULL)
01104             {
01105               if (strstr (idesc->name, "or.andcm"))
01106                 resolved = strstr (field, "or.andcm") != NULL;
01107               else if (strstr (idesc->name, "and.orcm"))
01108                 resolved = strstr (field, "and.orcm") != NULL;
01109               else if (strstr (idesc->name, "orcm"))
01110                 resolved = strstr (field, "or orcm") != NULL;
01111               else if (strstr (idesc->name, "or"))
01112                 resolved = strstr (field, "or orcm") != NULL;
01113               else if (strstr (idesc->name, "andcm"))
01114                 resolved = strstr (field, "and andcm") != NULL;
01115               else if (strstr (idesc->name, "and"))
01116                 resolved = strstr (field, "and andcm") != NULL;
01117               else if (strstr (idesc->name, "unc"))
01118                 resolved = strstr (field, "unc") != NULL;
01119               else
01120                 resolved = strcmp (field, "Field(ctype)==") == 0;
01121             }
01122         }
01123 
01124       if (resolved && format)
01125         {
01126           if (CONST_STRNEQ (idesc->name, "dep")
01127                    && strstr (format, "I13") != NULL)
01128             resolved = idesc->operands[1] == IA64_OPND_IMM8;
01129           else if (CONST_STRNEQ (idesc->name, "chk")
01130                    && strstr (format, "M21") != NULL)
01131             resolved = idesc->operands[0] == IA64_OPND_F2;
01132           else if (CONST_STRNEQ (idesc->name, "lfetch"))
01133             resolved = (strstr (format, "M14 M15") != NULL
01134                         && (idesc->operands[1] == IA64_OPND_R2
01135                             || idesc->operands[1] == IA64_OPND_IMM9b));
01136           else if (CONST_STRNEQ (idesc->name, "br.call")
01137                    && strstr (format, "B5") != NULL)
01138             resolved = idesc->operands[1] == IA64_OPND_B2;
01139           else if (CONST_STRNEQ (idesc->name, "br.call")
01140                    && strstr (format, "B3") != NULL)
01141             resolved = idesc->operands[1] == IA64_OPND_TGT25c;
01142           else if (CONST_STRNEQ (idesc->name, "brp")
01143                    && strstr (format, "B7") != NULL)
01144             resolved = idesc->operands[0] == IA64_OPND_B2;
01145           else if (strcmp (ic->name, "invala") == 0)
01146             resolved = strcmp (idesc->name, ic->name) == 0;
01147          else if (CONST_STRNEQ (idesc->name, "st")
01148                  && (strstr (format, "M5") != NULL
01149                      || strstr (format, "M10") != NULL))
01150            resolved = idesc->flags & IA64_OPCODE_POSTINC;
01151          else if (CONST_STRNEQ (idesc->name, "ld")
01152                  && (strstr (format, "M2 M3") != NULL
01153                      || strstr (format, "M12") != NULL
01154                      || strstr (format, "M7 M8") != NULL))
01155            resolved = idesc->flags & IA64_OPCODE_POSTINC;
01156           else
01157             resolved = 0;
01158         }
01159 
01160       /* Misc brl variations ('.cond' is optional); 
01161          plain brl matches brl.cond.  */
01162       if (!resolved
01163           && (strcmp (idesc->name, "brl") == 0
01164               || CONST_STRNEQ (idesc->name, "brl."))
01165           && strcmp (ic->name, "brl.cond") == 0)
01166         {
01167           resolved = 1;
01168         }
01169 
01170       /* Misc br variations ('.cond' is optional).  */
01171       if (!resolved 
01172           && (strcmp (idesc->name, "br") == 0
01173               || CONST_STRNEQ (idesc->name, "br."))
01174           && strcmp (ic->name, "br.cond") == 0)
01175         {
01176           if (format)
01177             resolved = (strstr (format, "B4") != NULL
01178                         && idesc->operands[0] == IA64_OPND_B2)
01179               || (strstr (format, "B1") != NULL
01180                   && idesc->operands[0] == IA64_OPND_TGT25c);
01181           else
01182             resolved = 1;
01183         }
01184 
01185       /* probe variations.  */
01186       if (!resolved && CONST_STRNEQ (idesc->name, "probe"))
01187         {
01188           resolved = strcmp (ic->name, "probe") == 0 
01189             && !((strstr (idesc->name, "fault") != NULL) 
01190                  ^ (format && strstr (format, "M40") != NULL));
01191         }
01192 
01193       /* mov variations.  */
01194       if (!resolved && is_mov)
01195         {
01196           if (plain_mov)
01197             {
01198               /* mov alias for fmerge.  */
01199               if (strcmp (ic->name, "fmerge") == 0)
01200                 {
01201                   resolved = idesc->operands[0] == IA64_OPND_F1
01202                     && idesc->operands[1] == IA64_OPND_F3;
01203                 }
01204               /* mov alias for adds (r3 or imm14).  */
01205               else if (strcmp (ic->name, "adds") == 0)
01206                 {
01207                   resolved = (idesc->operands[0] == IA64_OPND_R1
01208                               && (idesc->operands[1] == IA64_OPND_R3
01209                                   || (idesc->operands[1] == IA64_OPND_IMM14)));
01210                 }
01211               /* mov alias for addl.  */
01212               else if (strcmp (ic->name, "addl") == 0)
01213                 {
01214                   resolved = idesc->operands[0] == IA64_OPND_R1
01215                     && idesc->operands[1] == IA64_OPND_IMM22;
01216                 }
01217             }
01218 
01219           /* Some variants of mov and mov.[im].  */
01220           if (!resolved && CONST_STRNEQ (ic->name, "mov_"))
01221            resolved = in_iclass_mov_x (idesc, ic, format, field);
01222         }
01223 
01224       /* Keep track of this so we can flag any insn classes which aren't 
01225          mapped onto at least one real insn.  */
01226       if (resolved)
01227        ic->terminal_resolved = 1;
01228     }
01229   else for (i = 0; i < ic->nsubs; i++)
01230     {
01231       if (in_iclass (idesc, ics[ic->subs[i]], format, field, notep))
01232         {
01233           int j;
01234 
01235           for (j = 0; j < ic->nxsubs; j++)
01236            if (in_iclass (idesc, ics[ic->xsubs[j]], NULL, NULL, NULL))
01237              return 0;
01238 
01239           if (debug > 1)
01240             printf ("%s is in IC %s\n", idesc->name, ic->name);
01241 
01242           resolved = 1;
01243           break;
01244         }
01245     }
01246   
01247   /* If it's in this IC, add the IC note (if any) to the insn.  */
01248   if (resolved)
01249     {
01250       if (ic->note && notep)
01251         {
01252           if (*notep && *notep != ic->note)
01253            warn (_("overwriting note %d with note %d (IC:%s)\n"),
01254                 *notep, ic->note, ic->name);
01255 
01256           *notep = ic->note;
01257         }
01258     }
01259 
01260   return resolved;
01261 }
01262 
01263 
01264 static int
01265 lookup_regindex (const char *name, int specifier)
01266 {
01267   switch (specifier)
01268     {
01269     case IA64_RS_ARX:
01270       if (strstr (name, "[RSC]"))
01271         return 16;
01272       if (strstr (name, "[BSP]"))
01273         return 17;
01274       else if (strstr (name, "[BSPSTORE]"))
01275         return 18;
01276       else if (strstr (name, "[RNAT]"))
01277         return 19;
01278       else if (strstr (name, "[FCR]"))
01279         return 21;
01280       else if (strstr (name, "[EFLAG]"))
01281         return 24;
01282       else if (strstr (name, "[CSD]"))
01283         return 25;
01284       else if (strstr (name, "[SSD]"))
01285         return 26;
01286       else if (strstr (name, "[CFLG]"))
01287         return 27;
01288       else if (strstr (name, "[FSR]"))
01289         return 28;
01290       else if (strstr (name, "[FIR]"))
01291         return 29;
01292       else if (strstr (name, "[FDR]"))
01293         return 30;
01294       else if (strstr (name, "[CCV]"))
01295         return 32;
01296       else if (strstr (name, "[ITC]"))
01297         return 44;
01298       else if (strstr (name, "[PFS]"))
01299         return 64;
01300       else if (strstr (name, "[LC]"))
01301         return 65;
01302       else if (strstr (name, "[EC]"))
01303         return 66;
01304       abort ();
01305     case IA64_RS_CRX:
01306       if (strstr (name, "[DCR]"))
01307         return 0;
01308       else if (strstr (name, "[ITM]"))
01309         return 1;
01310       else if (strstr (name, "[IVA]"))
01311         return 2;
01312       else if (strstr (name, "[PTA]"))
01313         return 8;
01314       else if (strstr (name, "[GPTA]"))
01315         return 9;
01316       else if (strstr (name, "[IPSR]"))
01317         return 16;
01318       else if (strstr (name, "[ISR]"))
01319         return 17;
01320       else if (strstr (name, "[IIP]"))
01321         return 19;
01322       else if (strstr (name, "[IFA]"))
01323         return 20;
01324       else if (strstr (name, "[ITIR]"))
01325         return 21;
01326       else if (strstr (name, "[IIPA]"))
01327         return 22;
01328       else if (strstr (name, "[IFS]"))
01329         return 23;
01330       else if (strstr (name, "[IIM]"))
01331         return 24;
01332       else if (strstr (name, "[IHA]"))
01333         return 25;
01334       else if (strstr (name, "[LID]"))
01335         return 64;
01336       else if (strstr (name, "[IVR]"))
01337         return 65;
01338       else if (strstr (name, "[TPR]"))
01339         return 66;
01340       else if (strstr (name, "[EOI]"))
01341         return 67;
01342       else if (strstr (name, "[ITV]"))
01343         return 72;
01344       else if (strstr (name, "[PMV]"))
01345         return 73;
01346       else if (strstr (name, "[CMCV]"))
01347         return 74;
01348       abort ();
01349     case IA64_RS_PSR:
01350       if (strstr (name, ".be"))
01351         return 1;
01352       else if (strstr (name, ".up"))
01353         return 2;
01354       else if (strstr (name, ".ac"))
01355         return 3;
01356       else if (strstr (name, ".mfl"))
01357         return 4;
01358       else if (strstr (name, ".mfh"))
01359         return 5;
01360       else if (strstr (name, ".ic"))
01361         return 13;
01362       else if (strstr (name, ".i"))
01363         return 14;
01364       else if (strstr (name, ".pk"))
01365         return 15;
01366       else if (strstr (name, ".dt"))
01367         return 17;
01368       else if (strstr (name, ".dfl"))
01369         return 18;
01370       else if (strstr (name, ".dfh"))
01371         return 19;
01372       else if (strstr (name, ".sp"))
01373         return 20;
01374       else if (strstr (name, ".pp"))
01375         return 21;
01376       else if (strstr (name, ".di"))
01377         return 22;
01378       else if (strstr (name, ".si"))
01379         return 23;
01380       else if (strstr (name, ".db"))
01381         return 24;
01382       else if (strstr (name, ".lp"))
01383         return 25;
01384       else if (strstr (name, ".tb"))
01385         return 26;
01386       else if (strstr (name, ".rt"))
01387         return 27;
01388       else if (strstr (name, ".cpl"))
01389         return 32;
01390       else if (strstr (name, ".rs"))
01391         return 34;
01392       else if (strstr (name, ".mc"))
01393         return 35;
01394       else if (strstr (name, ".it"))
01395         return 36;
01396       else if (strstr (name, ".id"))
01397         return 37;
01398       else if (strstr (name, ".da"))
01399         return 38;
01400       else if (strstr (name, ".dd"))
01401         return 39;
01402       else if (strstr (name, ".ss"))
01403         return 40;
01404       else if (strstr (name, ".ri"))
01405         return 41;
01406       else if (strstr (name, ".ed"))
01407         return 43;
01408       else if (strstr (name, ".bn"))
01409         return 44;
01410       else if (strstr (name, ".ia"))
01411         return 45;
01412       else if (strstr (name, ".vm"))
01413         return 46;
01414       else
01415         abort ();
01416     default:
01417       break;
01418     }
01419   return REG_NONE;
01420 }
01421 
01422 static int
01423 lookup_specifier (const char *name)
01424 {
01425   if (strchr (name, '%'))
01426     {
01427       if (strstr (name, "AR[K%]") != NULL)
01428         return IA64_RS_AR_K;
01429       if (strstr (name, "AR[UNAT]") != NULL)
01430         return IA64_RS_AR_UNAT;
01431       if (strstr (name, "AR%, % in 8") != NULL)
01432         return IA64_RS_AR;
01433       if (strstr (name, "AR%, % in 48") != NULL)
01434         return IA64_RS_ARb;
01435       if (strstr (name, "BR%") != NULL)
01436         return IA64_RS_BR;
01437       if (strstr (name, "CR[IRR%]") != NULL)
01438         return IA64_RS_CR_IRR;
01439       if (strstr (name, "CR[LRR%]") != NULL)
01440         return IA64_RS_CR_LRR;
01441       if (strstr (name, "CR%") != NULL)
01442         return IA64_RS_CR;
01443       if (strstr (name, "FR%, % in 0") != NULL)
01444         return IA64_RS_FR;
01445       if (strstr (name, "FR%, % in 2") != NULL)
01446         return IA64_RS_FRb;
01447       if (strstr (name, "GR%") != NULL)
01448         return IA64_RS_GR;
01449       if (strstr (name, "PR%, % in 1 ") != NULL)
01450         return IA64_RS_PR;
01451       if (strstr (name, "PR%, % in 16 ") != NULL)
01452        return IA64_RS_PRr;
01453 
01454       warn (_("don't know how to specify %% dependency %s\n"),
01455            name);
01456     }
01457   else if (strchr (name, '#'))
01458     {
01459       if (strstr (name, "CPUID#") != NULL)
01460         return IA64_RS_CPUID;
01461       if (strstr (name, "DBR#") != NULL)
01462         return IA64_RS_DBR;
01463       if (strstr (name, "IBR#") != NULL)
01464         return IA64_RS_IBR;
01465       if (strstr (name, "MSR#") != NULL)
01466        return IA64_RS_MSR;
01467       if (strstr (name, "PKR#") != NULL)
01468         return IA64_RS_PKR;
01469       if (strstr (name, "PMC#") != NULL)
01470         return IA64_RS_PMC;
01471       if (strstr (name, "PMD#") != NULL)
01472         return IA64_RS_PMD;
01473       if (strstr (name, "RR#") != NULL)
01474         return IA64_RS_RR;
01475       
01476       warn (_("Don't know how to specify # dependency %s\n"),
01477            name);
01478     }
01479   else if (CONST_STRNEQ (name, "AR[FPSR]"))
01480     return IA64_RS_AR_FPSR;
01481   else if (CONST_STRNEQ (name, "AR["))
01482     return IA64_RS_ARX;
01483   else if (CONST_STRNEQ (name, "CR["))
01484     return IA64_RS_CRX;
01485   else if (CONST_STRNEQ (name, "PSR."))
01486     return IA64_RS_PSR;
01487   else if (strcmp (name, "InService*") == 0)
01488     return IA64_RS_INSERVICE;
01489   else if (strcmp (name, "GR0") == 0)
01490     return IA64_RS_GR0;
01491   else if (strcmp (name, "CFM") == 0)
01492     return IA64_RS_CFM;
01493   else if (strcmp (name, "PR63") == 0)
01494     return IA64_RS_PR63;
01495   else if (strcmp (name, "RSE") == 0)
01496     return IA64_RS_RSE;
01497 
01498   return IA64_RS_ANY;
01499 }
01500 
01501 static void
01502 print_dependency_table ()
01503 {
01504   int i, j;
01505 
01506   if (debug) 
01507     {
01508       for (i=0;i < iclen;i++)
01509         {
01510           if (ics[i]->is_class)
01511             {
01512               if (!ics[i]->nsubs)
01513                 {
01514                   if (ics[i]->comment)
01515                   warn (_("IC:%s [%s] has no terminals or sub-classes\n"),
01516                        ics[i]->name, ics[i]->comment);
01517                 else
01518                   warn (_("IC:%s has no terminals or sub-classes\n"),
01519                        ics[i]->name);
01520                 }
01521             }
01522           else 
01523             {
01524               if (!ics[i]->terminal_resolved && !ics[i]->orphan)
01525                 {
01526                   if (ics[i]->comment)
01527                   warn (_("no insns mapped directly to terminal IC %s [%s]"),
01528                        ics[i]->name, ics[i]->comment);
01529                 else
01530                   warn (_("no insns mapped directly to terminal IC %s\n"),
01531                        ics[i]->name);
01532                 }
01533             }
01534         }
01535 
01536       for (i = 0; i < iclen; i++)
01537         {
01538           if (ics[i]->orphan)
01539             {
01540               mark_used (ics[i], 1);
01541               warn (_("class %s is defined but not used\n"),
01542                   ics[i]->name);
01543             }
01544         }
01545 
01546       if (debug > 1)
01547        for (i = 0; i < rdepslen; i++)
01548          {  
01549            static const char *mode_str[] = { "RAW", "WAW", "WAR" };
01550 
01551            if (rdeps[i]->total_chks == 0)
01552              warn (_("Warning: rsrc %s (%s) has no chks%s\n"), 
01553                   rdeps[i]->name, mode_str[rdeps[i]->mode],
01554                   rdeps[i]->total_regs ? "" : " or regs");
01555            else if (rdeps[i]->total_regs == 0)
01556              warn (_("rsrc %s (%s) has no regs\n"),
01557                   rdeps[i]->name, mode_str[rdeps[i]->mode]);
01558          }
01559     }
01560 
01561   /* The dependencies themselves.  */
01562   printf ("static const struct ia64_dependency\ndependencies[] = {\n");
01563   for (i = 0; i < rdepslen; i++)
01564     {
01565       /* '%', '#', AR[], CR[], or PSR. indicates we need to specify the actual
01566          resource used.  */ 
01567       int specifier = lookup_specifier (rdeps[i]->name);
01568       int regindex = lookup_regindex (rdeps[i]->name, specifier);
01569 
01570       printf ("  { \"%s\", %d, %d, %d, %d, ",
01571               rdeps[i]->name, specifier,
01572               (int)rdeps[i]->mode, (int)rdeps[i]->semantics, regindex);
01573       if (rdeps[i]->semantics == IA64_DVS_OTHER)
01574        {
01575          const char *quote, *rest;
01576 
01577          putchar ('\"');
01578          rest = rdeps[i]->extra;
01579          quote = strchr (rest, '\"');
01580          while (quote != NULL)
01581            {
01582              printf ("%.*s\\\"", (int) (quote - rest), rest);
01583              rest = quote + 1;
01584              quote = strchr (rest, '\"');
01585            }
01586          printf ("%s\", ", rest);
01587        }
01588       else
01589        printf ("NULL, ");
01590       printf("},\n");
01591     }
01592   printf ("};\n\n");
01593 
01594   /* And dependency lists.  */
01595   for (i=0;i < dlistlen;i++)
01596     {
01597       int len = 2;
01598       printf ("static const unsigned short dep%d[] = {\n  ", i);
01599       for (j=0;j < dlists[i]->len; j++)
01600         {
01601           len += printf ("%d, ", dlists[i]->deps[j]);
01602           if (len > 75)
01603             {
01604               printf("\n  ");
01605               len = 2;
01606             }
01607         }
01608       printf ("\n};\n\n");
01609     }
01610 
01611   /* And opcode dependency list.  */
01612   printf ("#define NELS(X) (sizeof(X)/sizeof(X[0]))\n");
01613   printf ("static const struct ia64_opcode_dependency\n");
01614   printf ("op_dependencies[] = {\n");
01615   for (i = 0; i < opdeplen; i++)
01616     {
01617       printf ("  { ");
01618       if (opdeps[i]->chk == -1)
01619         printf ("0, NULL, ");
01620       else 
01621         printf ("NELS(dep%d), dep%d, ", opdeps[i]->chk, opdeps[i]->chk);
01622       if (opdeps[i]->reg == -1)
01623         printf ("0, NULL, ");
01624       else 
01625         printf ("NELS(dep%d), dep%d, ", opdeps[i]->reg, opdeps[i]->reg);
01626       printf ("},\n");
01627     }
01628   printf ("};\n\n");
01629 }
01630 
01631 
01632 /* Add STR to the string table.  */
01633 static struct string_entry *
01634 insert_string (char *str)
01635 {
01636   int start = 0, end = strtablen;
01637   int i, x;
01638 
01639   if (strtablen == strtabtotlen)
01640     {
01641       strtabtotlen += 20;
01642       string_table = (struct string_entry **)
01643        xrealloc (string_table, 
01644                 sizeof (struct string_entry **) * strtabtotlen);
01645     }
01646 
01647   if (strtablen == 0)
01648     {
01649       strtablen = 1;
01650       string_table[0] = tmalloc (struct string_entry);
01651       string_table[0]->s = xstrdup (str);
01652       string_table[0]->num = 0;
01653       return string_table[0];
01654     }
01655 
01656   if (strcmp (str, string_table[strtablen - 1]->s) > 0)
01657     i = end;
01658   else if (strcmp (str, string_table[0]->s) < 0)
01659     i = 0;
01660   else
01661     {
01662       while (1)
01663        {
01664          int c;
01665 
01666          i = (start + end) / 2;
01667          c = strcmp (str, string_table[i]->s);
01668 
01669          if (c < 0)
01670            end = i - 1;
01671          else if (c == 0)
01672            return string_table[i];
01673          else
01674            start = i + 1;
01675 
01676          if (start > end)
01677            break;
01678        }
01679     }
01680 
01681   for (; i > 0 && i < strtablen; i--)
01682     if (strcmp (str, string_table[i - 1]->s) > 0)
01683       break;
01684 
01685   for (; i < strtablen; i++)
01686     if (strcmp (str, string_table[i]->s) < 0)
01687       break;
01688 
01689   for (x = strtablen - 1; x >= i; x--)
01690     {
01691       string_table[x + 1] = string_table[x];
01692       string_table[x + 1]->num = x + 1;
01693     }
01694 
01695   string_table[i] = tmalloc (struct string_entry);
01696   string_table[i]->s = xstrdup (str);
01697   string_table[i]->num = i;
01698   strtablen++;
01699 
01700   return string_table[i];
01701 }
01702 
01703 static struct bittree *
01704 make_bittree_entry (void)
01705 {
01706   struct bittree *res = tmalloc (struct bittree);
01707 
01708   res->disent = NULL;
01709   res->bits[0] = NULL;
01710   res->bits[1] = NULL;
01711   res->bits[2] = NULL;
01712   res->skip_flag = 0;
01713   res->bits_to_skip = 0;
01714   return res;
01715 }
01716  
01717 
01718 static struct disent *
01719 add_dis_table_ent (which, insn, order, completer_index)
01720      struct disent *which;
01721      int insn;
01722      int order;
01723      int completer_index;
01724 {
01725   int ci = 0;
01726   struct disent *ent;
01727 
01728   if (which != NULL)
01729     {
01730       ent = which;
01731 
01732       ent->nextcnt++;
01733       while (ent->nexte != NULL)
01734        ent = ent->nexte;
01735 
01736       ent = (ent->nexte = tmalloc (struct disent));
01737     }
01738   else
01739     {
01740       ent = tmalloc (struct disent);
01741       ent->next_ent = disinsntable;
01742       disinsntable = ent;
01743       which = ent;
01744     }
01745   ent->nextcnt = 0;
01746   ent->nexte = NULL;
01747   ent->insn = insn;
01748   ent->priority = order;
01749 
01750   while (completer_index != 1)
01751     {
01752       ci = (ci << 1) | (completer_index & 1);
01753       completer_index >>= 1;
01754     }
01755   ent->completer_index = ci;
01756   return which;
01757 }
01758 
01759 static void
01760 finish_distable ()
01761 {
01762   struct disent *ent = disinsntable;
01763   struct disent *prev = ent;
01764 
01765   ent->ournum = 32768;
01766   while ((ent = ent->next_ent) != NULL)
01767     {
01768       ent->ournum = prev->ournum + prev->nextcnt + 1;
01769       prev = ent;
01770     }
01771 }
01772 
01773 static void
01774 insert_bit_table_ent (curr_ent, bit, opcode, mask, 
01775                       opcodenum, order, completer_index)
01776      struct bittree *curr_ent;
01777      int bit;
01778      ia64_insn opcode; 
01779      ia64_insn mask;
01780      int opcodenum;
01781      int order;
01782      int completer_index;
01783 {
01784   ia64_insn m;
01785   int b;
01786   struct bittree *next;
01787 
01788   if (bit == -1)
01789     {
01790       struct disent *nent = add_dis_table_ent (curr_ent->disent, 
01791                                                opcodenum, order,
01792                                           completer_index);
01793       curr_ent->disent = nent;
01794       return;
01795     }
01796 
01797   m = ((ia64_insn) 1) << bit;
01798 
01799   if (mask & m)
01800     b = (opcode & m) ? 1 : 0;
01801   else
01802     b = 2;
01803 
01804   next = curr_ent->bits[b];
01805   if (next == NULL)
01806     {
01807       next = make_bittree_entry ();
01808       curr_ent->bits[b] = next;
01809     }
01810   insert_bit_table_ent (next, bit - 1, opcode, mask, opcodenum, order,
01811                      completer_index);
01812 }
01813 
01814 static void
01815 add_dis_entry (first, opcode, mask, opcodenum, ent, completer_index)
01816      struct bittree *first;
01817      ia64_insn opcode;
01818      ia64_insn mask;
01819      int opcodenum;
01820      struct completer_entry *ent;
01821      int completer_index;
01822 {
01823   if (completer_index & (1 << 20))
01824     abort ();
01825 
01826   while (ent != NULL)
01827     {
01828       ia64_insn newopcode = (opcode & (~ ent->mask)) | ent->bits;
01829       add_dis_entry (first, newopcode, mask, opcodenum, ent->addl_entries,
01830                    (completer_index << 1) | 1);
01831 
01832       if (ent->is_terminal)
01833        {
01834          insert_bit_table_ent (bittree, 40, newopcode, mask, 
01835                                 opcodenum, opcode_count - ent->order - 1, 
01836                             (completer_index << 1) | 1);
01837        }
01838       completer_index <<= 1;
01839       ent = ent->alternative;
01840     }
01841 }
01842 
01843 /* This optimization pass combines multiple "don't care" nodes.  */
01844 static void
01845 compact_distree (ent)
01846      struct bittree *ent;
01847 {
01848 #define IS_SKIP(ent) \
01849     ((ent->bits[2] !=NULL) \
01850      && (ent->bits[0] == NULL && ent->bits[1] == NULL && ent->skip_flag == 0))
01851 
01852   int bitcnt = 0;
01853   struct bittree *nent = ent;
01854   int x;
01855 
01856   while (IS_SKIP (nent))
01857     {
01858       bitcnt++;
01859       nent = nent->bits[2];
01860     }
01861 
01862   if (bitcnt)
01863     {
01864       struct bittree *next = ent->bits[2];
01865 
01866       ent->bits[0] = nent->bits[0];
01867       ent->bits[1] = nent->bits[1];
01868       ent->bits[2] = nent->bits[2];
01869       ent->disent = nent->disent;
01870       ent->skip_flag = 1;
01871       ent->bits_to_skip = bitcnt;
01872       while (next != nent)
01873        {
01874          struct bittree *b = next;
01875          next = next->bits[2];
01876          free (b);
01877        }
01878       free (nent);
01879     }
01880 
01881   for (x = 0; x < 3; x++)
01882     {
01883       struct bittree *i = ent->bits[x];
01884 
01885       if (i != NULL)
01886        compact_distree (i);
01887     }
01888 }
01889 
01890 static unsigned char *insn_list;
01891 static int insn_list_len = 0;
01892 static int tot_insn_list_len = 0;
01893 
01894 /* Generate the disassembler state machine corresponding to the tree
01895    in ENT.  */
01896 static void
01897 gen_dis_table (ent)
01898      struct bittree *ent;
01899 {
01900   int x;
01901   int our_offset = insn_list_len;
01902   int bitsused = 5;
01903   int totbits = bitsused;
01904   int needed_bytes;
01905   int zero_count = 0;
01906   int zero_dest = 0; /* Initialize this with 0 to keep gcc quiet...  */
01907 
01908   /* If this is a terminal entry, there's no point in skipping any
01909      bits.  */
01910   if (ent->skip_flag && ent->bits[0] == NULL && ent->bits[1] == NULL &&
01911       ent->bits[2] == NULL)
01912     {
01913       if (ent->disent == NULL)
01914        abort ();
01915       else
01916        ent->skip_flag = 0;
01917     }
01918 
01919   /* Calculate the amount of space needed for this entry, or at least
01920      a conservatively large approximation.  */
01921   if (ent->skip_flag)
01922     totbits += 5;
01923 
01924   for (x = 1; x < 3; x++)
01925     if (ent->bits[x] != NULL)
01926       totbits += 16;
01927 
01928   if (ent->disent != NULL)
01929     {
01930       if (ent->bits[2] != NULL)
01931        abort ();
01932 
01933       totbits += 16;
01934     }
01935 
01936   /* Now allocate the space.  */
01937   needed_bytes = (totbits + 7) / 8;
01938   if ((needed_bytes + insn_list_len) > tot_insn_list_len)
01939     {
01940       tot_insn_list_len += 256;
01941       insn_list = (unsigned char *) xrealloc (insn_list, tot_insn_list_len);
01942     }
01943   our_offset = insn_list_len;
01944   insn_list_len += needed_bytes;
01945   memset (insn_list + our_offset, 0, needed_bytes);
01946 
01947   /* Encode the skip entry by setting bit 6 set in the state op field,
01948      and store the # of bits to skip immediately after.  */
01949   if (ent->skip_flag)
01950     {
01951       bitsused += 5;
01952       insn_list[our_offset + 0] |= 0x40 | ((ent->bits_to_skip >> 2) & 0xf);
01953       insn_list[our_offset + 1] |= ((ent->bits_to_skip & 3) << 6);
01954     }
01955 
01956 #define IS_ONLY_IFZERO(ENT) \
01957   ((ENT)->bits[0] != NULL && (ENT)->bits[1] == NULL && (ENT)->bits[2] == NULL \
01958    && (ENT)->disent == NULL && (ENT)->skip_flag == 0)
01959 
01960   /* Store an "if (bit is zero)" instruction by setting bit 7 in the
01961      state op field.  */
01962   if (ent->bits[0] != NULL)
01963     {
01964       struct bittree *nent = ent->bits[0];
01965       zero_count = 0;
01966 
01967       insn_list[our_offset] |= 0x80;
01968 
01969       /* We can encode sequences of multiple "if (bit is zero)" tests
01970         by storing the # of zero bits to check in the lower 3 bits of
01971         the instruction.  However, this only applies if the state
01972         solely tests for a zero bit.  */
01973 
01974       if (IS_ONLY_IFZERO (ent))
01975        {
01976          while (IS_ONLY_IFZERO (nent) && zero_count < 7)
01977            {
01978              nent = nent->bits[0];
01979              zero_count++;
01980            }
01981 
01982          insn_list[our_offset + 0] |= zero_count;
01983        }
01984       zero_dest = insn_list_len;
01985       gen_dis_table (nent);
01986     }
01987 
01988   /* Now store the remaining tests.  We also handle a sole "termination
01989      entry" by storing it as an "any bit" test.  */
01990 
01991   for (x = 1; x < 3; x++)
01992     {
01993       if (ent->bits[x] != NULL || (x == 2 && ent->disent != NULL))
01994        {
01995          struct bittree *i = ent->bits[x];
01996          int idest;
01997          int currbits = 15;
01998 
01999          if (i != NULL)
02000            {
02001              /* If the instruction being branched to only consists of
02002                a termination entry, use the termination entry as the
02003                place to branch to instead.  */
02004              if (i->bits[0] == NULL && i->bits[1] == NULL
02005                 && i->bits[2] == NULL && i->disent != NULL)
02006               {
02007                 idest = i->disent->ournum;
02008                 i = NULL;
02009               }
02010              else
02011               idest = insn_list_len - our_offset;
02012            }
02013          else
02014            idest = ent->disent->ournum;
02015 
02016          /* If the destination offset for the if (bit is 1) test is less 
02017             than 256 bytes away, we can store it as 8-bits instead of 16;
02018             the instruction has bit 5 set for the 16-bit address, and bit
02019             4 for the 8-bit address.  Since we've already allocated 16
02020             bits for the address we need to deallocate the space.
02021 
02022             Note that branchings within the table are relative, and
02023             there are no branches that branch past our instruction yet
02024             so we do not need to adjust any other offsets.  */
02025          if (x == 1)
02026            {
02027              if (idest <= 256)
02028               {
02029                 int start = our_offset + bitsused / 8 + 1;
02030 
02031                 memmove (insn_list + start,
02032                         insn_list + start + 1,
02033                         insn_list_len - (start + 1));
02034                 currbits = 7;
02035                 totbits -= 8;
02036                 needed_bytes--;
02037                 insn_list_len--;
02038                 insn_list[our_offset] |= 0x10;
02039                 idest--;
02040               }
02041              else
02042               insn_list[our_offset] |= 0x20;
02043            }
02044          else
02045            {
02046              /* An instruction which solely consists of a termination
02047                marker and whose disassembly name index is < 4096
02048                can be stored in 16 bits.  The encoding is slightly
02049                odd; the upper 4 bits of the instruction are 0x3, and
02050                bit 3 loses its normal meaning.  */
02051 
02052              if (ent->bits[0] == NULL && ent->bits[1] == NULL
02053                 && ent->bits[2] == NULL && ent->skip_flag == 0
02054                 && ent->disent != NULL
02055                 && ent->disent->ournum < (32768 + 4096))
02056               {
02057                 int start = our_offset + bitsused / 8 + 1;
02058 
02059                 memmove (insn_list + start,
02060                         insn_list + start + 1,
02061                         insn_list_len - (start + 1));
02062                 currbits = 11;
02063                 totbits -= 5;
02064                 bitsused--;
02065                 needed_bytes--;
02066                 insn_list_len--;
02067                 insn_list[our_offset] |= 0x30;
02068                 idest &= ~32768;
02069               }
02070              else
02071               insn_list[our_offset] |= 0x08;
02072            }
02073 
02074          if (debug)
02075            {
02076              int id = idest;
02077 
02078              if (i == NULL)
02079               id |= 32768;
02080              else if (! (id & 32768))
02081               id += our_offset;
02082 
02083              if (x == 1)
02084               printf ("%d: if (1) goto %d\n", our_offset, id);
02085              else
02086               printf ("%d: try %d\n", our_offset, id);
02087            }
02088 
02089          /* Store the address of the entry being branched to.  */
02090          while (currbits >= 0)
02091            {
02092              unsigned char *byte = insn_list + our_offset + bitsused / 8;
02093 
02094              if (idest & (1 << currbits))
02095               *byte |= (1 << (7 - (bitsused % 8)));
02096 
02097              bitsused++;
02098              currbits--;
02099            }
02100 
02101          /* Now generate the states for the entry being branched to.  */
02102          if (i != NULL)
02103            gen_dis_table (i);
02104        }
02105     }
02106 
02107   if (debug)
02108     {
02109       if (ent->skip_flag)
02110        printf ("%d: skipping %d\n", our_offset, ent->bits_to_skip);
02111   
02112       if (ent->bits[0] != NULL)
02113        printf ("%d: if (0:%d) goto %d\n", our_offset, zero_count + 1,
02114               zero_dest);
02115     }
02116 
02117   if (bitsused != totbits)
02118     abort ();
02119 }
02120 
02121 static void
02122 print_dis_table (void)
02123 {
02124   int x;
02125   struct disent *cent = disinsntable;
02126 
02127   printf ("static const char dis_table[] = {\n");
02128   for (x = 0; x < insn_list_len; x++)
02129     {
02130       if ((x > 0) && ((x % 12) == 0))
02131        printf ("\n");
02132 
02133       printf ("0x%02x, ", insn_list[x]);
02134     }
02135   printf ("\n};\n\n");
02136 
02137   printf ("static const struct ia64_dis_names ia64_dis_names[] = {\n");
02138   while (cent != NULL)
02139     {
02140       struct disent *ent = cent;
02141 
02142       while (ent != NULL)
02143        {
02144          printf ("{ 0x%x, %d, %d, %d },\n", ent->completer_index,
02145                 ent->insn, (ent->nexte != NULL ? 1 : 0),
02146                   ent->priority);
02147          ent = ent->nexte;
02148        }
02149       cent = cent->next_ent;
02150     }
02151   printf ("};\n\n");
02152 }
02153 
02154 static void
02155 generate_disassembler (void)
02156 {
02157   int i;
02158 
02159   bittree = make_bittree_entry ();
02160 
02161   for (i = 0; i < otlen; i++)
02162     {
02163       struct main_entry *ptr = ordered_table[i];
02164 
02165       if (ptr->opcode->type != IA64_TYPE_DYN)
02166        add_dis_entry (bittree,
02167                      ptr->opcode->opcode, ptr->opcode->mask, 
02168                      ptr->main_index,
02169                      ptr->completers, 1);
02170     }
02171 
02172   compact_distree (bittree);
02173   finish_distable ();
02174   gen_dis_table (bittree);
02175 
02176   print_dis_table ();
02177 }
02178 
02179 static void
02180 print_string_table (void)
02181 {
02182   int x;
02183   char lbuf[80], buf[80];
02184   int blen = 0;
02185 
02186   printf ("static const char * const ia64_strings[] = {\n");
02187   lbuf[0] = '\0';
02188 
02189   for (x = 0; x < strtablen; x++)
02190     {
02191       int len;
02192       
02193       if (strlen (string_table[x]->s) > 75)
02194        abort ();
02195 
02196       sprintf (buf, " \"%s\",", string_table[x]->s);
02197       len = strlen (buf);
02198 
02199       if ((blen + len) > 75)
02200        {
02201          printf (" %s\n", lbuf);
02202          lbuf[0] = '\0';
02203          blen = 0;
02204        }
02205       strcat (lbuf, buf);
02206       blen += len;
02207     }
02208 
02209   if (blen > 0)
02210     printf (" %s\n", lbuf);
02211 
02212   printf ("};\n\n");
02213 }
02214 
02215 static struct completer_entry **glist;
02216 static int glistlen = 0;
02217 static int glisttotlen = 0;
02218 
02219 /* If the completer trees ENT1 and ENT2 are equal, return 1.  */
02220 
02221 static int
02222 completer_entries_eq (ent1, ent2)
02223      struct completer_entry *ent1, *ent2;
02224 {
02225   while (ent1 != NULL && ent2 != NULL)
02226     {
02227       if (ent1->name->num != ent2->name->num
02228          || ent1->bits != ent2->bits
02229          || ent1->mask != ent2->mask
02230          || ent1->is_terminal != ent2->is_terminal
02231           || ent1->dependencies != ent2->dependencies
02232           || ent1->order != ent2->order)
02233        return 0;
02234 
02235       if (! completer_entries_eq (ent1->addl_entries, ent2->addl_entries))
02236        return 0;
02237 
02238       ent1 = ent1->alternative;
02239       ent2 = ent2->alternative;
02240     }
02241 
02242   return ent1 == ent2;
02243 }
02244 
02245 /* Insert ENT into the global list of completers and return it.  If an
02246    equivalent entry (according to completer_entries_eq) already exists,
02247    it is returned instead.  */
02248 static struct completer_entry *
02249 insert_gclist (struct completer_entry *ent)
02250 {
02251   if (ent != NULL)
02252     {
02253       int i;
02254       int x;
02255       int start = 0, end;
02256 
02257       ent->addl_entries = insert_gclist (ent->addl_entries);
02258       ent->alternative = insert_gclist (ent->alternative);
02259 
02260       i = glistlen / 2;
02261       end = glistlen;
02262 
02263       if (glisttotlen == glistlen)
02264        {
02265          glisttotlen += 20;
02266          glist = (struct completer_entry **)
02267            xrealloc (glist, sizeof (struct completer_entry *) * glisttotlen);
02268        }
02269 
02270       if (glistlen == 0)
02271        {
02272          glist[0] = ent;
02273          glistlen = 1;
02274          return ent;
02275        }
02276 
02277       if (ent->name->num < glist[0]->name->num)
02278        i = 0;
02279       else if (ent->name->num > glist[end - 1]->name->num)
02280        i = end;
02281       else
02282        {
02283          int c;
02284 
02285          while (1)
02286            {
02287              i = (start + end) / 2;
02288              c = ent->name->num - glist[i]->name->num;
02289 
02290              if (c < 0)
02291               end = i - 1;
02292              else if (c == 0)
02293               {
02294                 while (i > 0 
02295                       && ent->name->num == glist[i - 1]->name->num)
02296                   i--;
02297 
02298                 break;
02299               }
02300              else
02301               start = i + 1;
02302 
02303              if (start > end)
02304               break;
02305            }
02306 
02307          if (c == 0)
02308            {
02309              while (i < glistlen)
02310               {
02311                 if (ent->name->num != glist[i]->name->num)
02312                   break;
02313 
02314                 if (completer_entries_eq (ent, glist[i]))
02315                   return glist[i];
02316 
02317                 i++;
02318               }
02319            }
02320        }
02321 
02322       for (; i > 0 && i < glistlen; i--)
02323        if (ent->name->num >= glist[i - 1]->name->num)
02324          break;
02325 
02326       for (; i < glistlen; i++)
02327        if (ent->name->num < glist[i]->name->num)
02328          break;
02329 
02330       for (x = glistlen - 1; x >= i; x--)
02331        glist[x + 1] = glist[x];
02332 
02333       glist[i] = ent;
02334       glistlen++;
02335     }
02336   return ent;
02337 }
02338 
02339 static int
02340 get_prefix_len (name)
02341      const char *name;
02342 {
02343   char *c;
02344 
02345   if (name[0] == '\0')
02346     return 0;
02347 
02348   c = strchr (name, '.');
02349   if (c != NULL)
02350     return c - name;
02351   else
02352     return strlen (name);
02353 }
02354 
02355 static void
02356 compute_completer_bits (ment, ent)
02357      struct main_entry *ment;
02358      struct completer_entry *ent;
02359 {
02360   while (ent != NULL)
02361     {
02362       compute_completer_bits (ment, ent->addl_entries);
02363 
02364       if (ent->is_terminal)
02365        {
02366          ia64_insn mask = 0;
02367          ia64_insn our_bits = ent->bits;
02368          struct completer_entry *p = ent->parent;
02369          ia64_insn p_bits;
02370          int x;
02371 
02372          while (p != NULL && ! p->is_terminal)
02373            p = p->parent;
02374       
02375          if (p != NULL)
02376            p_bits = p->bits;
02377          else
02378            p_bits = ment->opcode->opcode;
02379 
02380          for (x = 0; x < 64; x++)
02381            {
02382              ia64_insn m = ((ia64_insn) 1) << x;
02383 
02384              if ((p_bits & m) != (our_bits & m))
02385               mask |= m;
02386              else
02387               our_bits &= ~m;
02388            }
02389          ent->bits = our_bits;
02390          ent->mask = mask;
02391        }
02392       else
02393        {
02394          ent->bits = 0;
02395          ent->mask = 0;
02396        }
02397 
02398       ent = ent->alternative;
02399     }
02400 }
02401 
02402 /* Find identical completer trees that are used in different
02403    instructions and collapse their entries.  */
02404 static void
02405 collapse_redundant_completers (void)
02406 {
02407   struct main_entry *ptr;
02408   int x;
02409 
02410   for (ptr = maintable; ptr != NULL; ptr = ptr->next)
02411     {
02412       if (ptr->completers == NULL)
02413        abort ();
02414 
02415       compute_completer_bits (ptr, ptr->completers);
02416       ptr->completers = insert_gclist (ptr->completers);
02417     }
02418 
02419   /* The table has been finalized, now number the indexes.  */
02420   for (x = 0; x < glistlen; x++)
02421     glist[x]->num = x;
02422 }
02423 
02424 
02425 /* Attach two lists of dependencies to each opcode.
02426    1) all resources which, when already marked in use, conflict with this
02427    opcode (chks) 
02428    2) all resources which must be marked in use when this opcode is used
02429    (regs).  */
02430 static int
02431 insert_opcode_dependencies (opc, cmp)
02432      struct ia64_opcode *opc;
02433      struct completer_entry *cmp ATTRIBUTE_UNUSED;
02434 {
02435   /* Note all resources which point to this opcode.  rfi has the most chks
02436      (79) and cmpxchng has the most regs (54) so 100 here should be enough.  */
02437   int i;
02438   int nregs = 0;
02439   unsigned short regs[256];                  
02440   int nchks = 0;
02441   unsigned short chks[256];
02442   /* Flag insns for which no class matched; there should be none.  */
02443   int no_class_found = 1;
02444 
02445   for (i = 0; i < rdepslen; i++)
02446     {
02447       struct rdep *rs = rdeps[i];
02448       int j;
02449 
02450       if (strcmp (opc->name, "cmp.eq.and") == 0
02451           && CONST_STRNEQ (rs->name, "PR%")
02452           && rs->mode == 1)
02453         no_class_found = 99;
02454 
02455       for (j=0; j < rs->nregs;j++)
02456         {
02457           int ic_note = 0;
02458 
02459           if (in_iclass (opc, ics[rs->regs[j]], NULL, NULL, &ic_note))
02460             {
02461               /* We can ignore ic_note 11 for non PR resources.  */
02462               if (ic_note == 11 && ! CONST_STRNEQ (rs->name, "PR"))
02463                 ic_note = 0;
02464 
02465               if (ic_note != 0 && rs->regnotes[j] != 0
02466                   && ic_note != rs->regnotes[j]
02467                   && !(ic_note == 11 && rs->regnotes[j] == 1))
02468                 warn (_("IC note %d in opcode %s (IC:%s) conflicts with resource %s note %d\n"),
02469                     ic_note, opc->name, ics[rs->regs[j]]->name,
02470                     rs->name, rs->regnotes[j]);
02471               /* Instruction class notes override resource notes.
02472                  So far, only note 11 applies to an IC instead of a resource,
02473                  and note 11 implies note 1.  */
02474               if (ic_note)
02475                 regs[nregs++] = RDEP(ic_note, i);
02476               else
02477                 regs[nregs++] = RDEP(rs->regnotes[j], i);
02478               no_class_found = 0;
02479               ++rs->total_regs;
02480             }
02481         }
02482 
02483       for (j = 0; j < rs->nchks; j++)
02484         {
02485           int ic_note = 0;
02486 
02487           if (in_iclass (opc, ics[rs->chks[j]], NULL, NULL, &ic_note))
02488             {
02489               /* We can ignore ic_note 11 for non PR resources.  */
02490               if (ic_note == 11 && ! CONST_STRNEQ (rs->name, "PR"))
02491                 ic_note = 0;
02492 
02493               if (ic_note != 0 && rs->chknotes[j] != 0
02494                   && ic_note != rs->chknotes[j]
02495                   && !(ic_note == 11 && rs->chknotes[j] == 1))
02496                 warn (_("IC note %d for opcode %s (IC:%s) conflicts with resource %s note %d\n"),
02497                     ic_note, opc->name, ics[rs->chks[j]]->name,
02498                     rs->name, rs->chknotes[j]);
02499               if (ic_note)
02500                 chks[nchks++] = RDEP(ic_note, i);
02501               else
02502                 chks[nchks++] = RDEP(rs->chknotes[j], i);
02503               no_class_found = 0;
02504               ++rs->total_chks;
02505             }
02506         }
02507     }
02508 
02509   if (no_class_found)
02510     warn (_("opcode %s has no class (ops %d %d %d)\n"),
02511          opc->name, 
02512          opc->operands[0], opc->operands[1], opc->operands[2]);
02513 
02514   return insert_dependencies (nchks, chks, nregs, regs);
02515 }
02516 
02517 static void
02518 insert_completer_entry (opc, tabent, order)
02519      struct ia64_opcode *opc;
02520      struct main_entry *tabent;
02521      int order;
02522 {
02523   struct completer_entry **ptr = &tabent->completers;
02524   struct completer_entry *parent = NULL;
02525   char pcopy[129], *prefix;
02526   int at_end = 0;
02527 
02528   if (strlen (opc->name) > 128)
02529     abort ();
02530 
02531   strcpy (pcopy, opc->name);
02532   prefix = pcopy + get_prefix_len (pcopy);
02533 
02534   if (prefix[0] != '\0')
02535     prefix++;
02536 
02537   while (! at_end)
02538     {
02539       int need_new_ent = 1;
02540       int plen = get_prefix_len (prefix);
02541       struct string_entry *sent;
02542 
02543       at_end = (prefix[plen] == '\0');
02544       prefix[plen] = '\0';
02545       sent = insert_string (prefix);
02546 
02547       while (*ptr != NULL)
02548        {
02549          int cmpres = sent->num - (*ptr)->name->num;
02550 
02551          if (cmpres == 0)
02552            {
02553              need_new_ent = 0;
02554              break;
02555            }
02556          else
02557            ptr = &((*ptr)->alternative);
02558        }
02559 
02560       if (need_new_ent)
02561        {
02562          struct completer_entry *nent = tmalloc (struct completer_entry);
02563 
02564          nent->name = sent;
02565          nent->parent = parent;
02566          nent->addl_entries = NULL;
02567          nent->alternative = *ptr;
02568          *ptr = nent;
02569          nent->is_terminal = 0;
02570           nent->dependencies = -1;
02571        }
02572 
02573       if (! at_end)
02574        {
02575          parent = *ptr;
02576          ptr = &((*ptr)->addl_entries);
02577          prefix += plen + 1;
02578        }
02579     }
02580 
02581   if ((*ptr)->is_terminal)
02582     abort ();
02583 
02584   (*ptr)->is_terminal = 1;
02585   (*ptr)->mask = (ia64_insn)-1;
02586   (*ptr)->bits = opc->opcode;
02587   (*ptr)->dependencies = insert_opcode_dependencies (opc, *ptr);
02588   (*ptr)->order = order;
02589 }
02590 
02591 static void
02592 print_completer_entry (ent)
02593      struct completer_entry *ent;
02594 {
02595   int moffset = 0;
02596   ia64_insn mask = ent->mask, bits = ent->bits;
02597 
02598   if (mask != 0)
02599     {
02600       while (! (mask & 1))
02601        {
02602          moffset++;
02603          mask = mask >> 1;
02604          bits = bits >> 1;
02605        }
02606 
02607       if (bits & 0xffffffff00000000LL)
02608        abort ();
02609     }
02610   
02611   printf ("  { 0x%x, 0x%x, %d, %d, %d, %d, %d, %d },\n",
02612          (int)bits,
02613          (int)mask,
02614          ent->name->num,
02615          ent->alternative != NULL ? ent->alternative->num : -1,
02616          ent->addl_entries != NULL ? ent->addl_entries->num : -1,
02617          moffset,
02618          ent->is_terminal ? 1 : 0,
02619           ent->dependencies);
02620 }
02621 
02622 static void
02623 print_completer_table ()
02624 {
02625   int x;
02626 
02627   printf ("static const struct ia64_completer_table\ncompleter_table[] = {\n");
02628   for (x = 0; x < glistlen; x++)
02629     print_completer_entry (glist[x]);
02630   printf ("};\n\n");
02631 }
02632 
02633 static int
02634 opcodes_eq (opc1, opc2)
02635      struct ia64_opcode *opc1;
02636      struct ia64_opcode *opc2;
02637 {
02638   int x;
02639   int plen1, plen2;
02640 
02641   if ((opc1->mask != opc2->mask) || (opc1->type != opc2->type) 
02642       || (opc1->num_outputs != opc2->num_outputs)
02643       || (opc1->flags != opc2->flags))
02644     return 0;
02645 
02646   for (x = 0; x < 5; x++)
02647     if (opc1->operands[x] != opc2->operands[x])
02648       return 0;
02649 
02650   plen1 = get_prefix_len (opc1->name);
02651   plen2 = get_prefix_len (opc2->name);
02652 
02653   if (plen1 == plen2 && (memcmp (opc1->name, opc2->name, plen1) == 0))
02654     return 1;
02655 
02656   return 0;
02657 }
02658 
02659 static void
02660 add_opcode_entry (opc)
02661      struct ia64_opcode *opc;
02662 {
02663   struct main_entry **place;
02664   struct string_entry *name;
02665   char prefix[129];
02666   int found_it = 0;
02667 
02668   if (strlen (opc->name) > 128)
02669     abort ();
02670 
02671   place = &maintable;
02672   strcpy (prefix, opc->name);
02673   prefix[get_prefix_len (prefix)] = '\0';
02674   name = insert_string (prefix);
02675 
02676   /* Walk the list of opcode table entries.  If it's a new
02677      instruction, allocate and fill in a new entry.  Note 
02678      the main table is alphabetical by opcode name.  */
02679 
02680   while (*place != NULL)
02681     {
02682       if ((*place)->name->num == name->num
02683          && opcodes_eq ((*place)->opcode, opc))
02684        {
02685          found_it = 1;
02686          break;
02687        }
02688       if ((*place)->name->num > name->num)
02689        break;
02690 
02691       place = &((*place)->next);
02692     }
02693   if (! found_it)
02694     {
02695       struct main_entry *nent = tmalloc (struct main_entry);
02696 
02697       nent->name = name;
02698       nent->opcode = opc;
02699       nent->next = *place;
02700       nent->completers = 0;
02701       *place = nent;
02702 
02703       if (otlen == ottotlen)
02704         {
02705           ottotlen += 20;
02706           ordered_table = (struct main_entry **)
02707             xrealloc (ordered_table, sizeof (struct main_entry *) * ottotlen);
02708         }
02709       ordered_table[otlen++] = nent;
02710     }
02711 
02712   insert_completer_entry (opc, *place, opcode_count++);
02713 }
02714 
02715 static void
02716 print_main_table (void)
02717 {
02718   struct main_entry *ptr = maintable;
02719   int index = 0;
02720 
02721   printf ("static const struct ia64_main_table\nmain_table[] = {\n");
02722   while (ptr != NULL)
02723     {
02724       printf ("  { %d, %d, %d, 0x",
02725              ptr->name->num,
02726              ptr->opcode->type,
02727              ptr->opcode->num_outputs);
02728       opcode_fprintf_vma (stdout, ptr->opcode->opcode);
02729       printf ("ull, 0x");
02730       opcode_fprintf_vma (stdout, ptr->opcode->mask);
02731       printf ("ull, { %d, %d, %d, %d, %d }, 0x%x, %d, },\n",
02732              ptr->opcode->operands[0],
02733              ptr->opcode->operands[1],
02734              ptr->opcode->operands[2],
02735              ptr->opcode->operands[3],
02736              ptr->opcode->operands[4],
02737              ptr->opcode->flags,
02738              ptr->completers->num);
02739 
02740       ptr->main_index = index++;
02741 
02742       ptr = ptr->next;
02743     }
02744   printf ("};\n\n");
02745 }
02746 
02747 static void
02748 shrink (table)
02749      struct ia64_opcode *table;
02750 {
02751   int curr_opcode;
02752 
02753   for (curr_opcode = 0; table[curr_opcode].name != NULL; curr_opcode++)
02754     {
02755       add_opcode_entry (table + curr_opcode);
02756       if (table[curr_opcode].num_outputs == 2
02757          && ((table[curr_opcode].operands[0] == IA64_OPND_P1
02758               && table[curr_opcode].operands[1] == IA64_OPND_P2)
02759              || (table[curr_opcode].operands[0] == IA64_OPND_P2
02760                 && table[curr_opcode].operands[1] == IA64_OPND_P1)))
02761        {
02762          struct ia64_opcode *alias = tmalloc(struct ia64_opcode);
02763          unsigned i;
02764 
02765          *alias = table[curr_opcode];
02766          for (i = 2; i < NELEMS (alias->operands); ++i)
02767            alias->operands[i - 1] = alias->operands[i];
02768          alias->operands[NELEMS (alias->operands) - 1] = IA64_OPND_NIL;
02769          --alias->num_outputs;
02770          alias->flags |= PSEUDO;
02771          add_opcode_entry (alias);
02772        }
02773     }
02774 }
02775 
02776 
02777 /* Program options.  */
02778 #define OPTION_SRCDIR       200
02779 
02780 struct option long_options[] = 
02781 {
02782   {"srcdir",  required_argument, NULL, OPTION_SRCDIR},
02783   {"debug",   no_argument,       NULL, 'd'},
02784   {"version", no_argument,       NULL, 'V'},
02785   {"help",    no_argument,       NULL, 'h'},
02786   {0,         no_argument,       NULL, 0}
02787 };
02788 
02789 static void
02790 print_version (void)
02791 {
02792   printf ("%s: version 1.0\n", program_name);
02793   xexit (0);
02794 }
02795 
02796 static void
02797 usage (FILE * stream, int status)
02798 {
02799   fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
02800           program_name);
02801   xexit (status);
02802 }
02803 
02804 int
02805 main (int argc, char **argv)
02806 {
02807   extern int chdir (char *);
02808   char *srcdir = NULL;
02809   int c;
02810   
02811   program_name = *argv;
02812   xmalloc_set_program_name (program_name);
02813 
02814   while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
02815     switch (c)
02816       {
02817       case OPTION_SRCDIR:
02818        srcdir = optarg;
02819        break;
02820       case 'V':
02821       case 'v':
02822        print_version ();
02823        break;
02824       case 'd':
02825        debug = 1;
02826        break;
02827       case 'h':
02828       case '?':
02829        usage (stderr, 0);
02830       default:
02831       case 0:
02832        break;
02833       }
02834 
02835   if (optind != argc)
02836     usage (stdout, 1);
02837 
02838   if (srcdir != NULL) 
02839     if (chdir (srcdir) != 0)
02840       fail (_("unable to change directory to \"%s\", errno = %s\n"),
02841            srcdir, strerror (errno));
02842 
02843   load_insn_classes ();
02844   load_dependencies ();
02845 
02846   shrink (ia64_opcodes_a);
02847   shrink (ia64_opcodes_b);
02848   shrink (ia64_opcodes_f);
02849   shrink (ia64_opcodes_i);
02850   shrink (ia64_opcodes_m);
02851   shrink (ia64_opcodes_x);
02852   shrink (ia64_opcodes_d);
02853 
02854   collapse_redundant_completers ();
02855 
02856   printf ("/* This file is automatically generated by ia64-gen.  Do not edit!  */\n");
02857   print_string_table ();
02858   print_dependency_table ();
02859   print_completer_table ();
02860   print_main_table ();
02861 
02862   generate_disassembler ();
02863 
02864   exit (0);
02865 }