ia64-gen.c revision 84865
184865Sobrien/* ia64-gen.c -- Generate a shrunk set of opcode tables
284865Sobrien   Copyright 1999, 2000 Free Software Foundation, Inc.
384865Sobrien   Written by Bob Manson, Cygnus Solutions, <manson@cygnus.com>
484865Sobrien
584865Sobrien   This file is part of GDB, GAS, and the GNU binutils.
684865Sobrien
784865Sobrien   GDB, GAS, and the GNU binutils are free software; you can redistribute
884865Sobrien   them and/or modify them under the terms of the GNU General Public
984865Sobrien   License as published by the Free Software Foundation; either version
1084865Sobrien   2, or (at your option) any later version.
1184865Sobrien
1284865Sobrien   GDB, GAS, and the GNU binutils are distributed in the hope that they
1384865Sobrien   will be useful, but WITHOUT ANY WARRANTY; without even the implied
1484865Sobrien   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1584865Sobrien   the GNU General Public License for more details.
1684865Sobrien
1784865Sobrien   You should have received a copy of the GNU General Public License
1884865Sobrien   along with this file; see the file COPYING.  If not, write to the
1984865Sobrien   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2084865Sobrien   02111-1307, USA.  */
2184865Sobrien
2284865Sobrien/* While the ia64-opc-* set of opcode tables are easy to maintain,
2384865Sobrien   they waste a tremendous amount of space.  ia64-gen rearranges the
2484865Sobrien   instructions into a directed acyclic graph (DAG) of instruction opcodes and
2584865Sobrien   their possible completers, as well as compacting the set of strings used.
2684865Sobrien
2784865Sobrien   The disassembler table consists of a state machine that does
2884865Sobrien   branching based on the bits of the opcode being disassembled.  The
2984865Sobrien   state encodings have been chosen to minimize the amount of space
3084865Sobrien   required.
3184865Sobrien
3284865Sobrien   The resource table is constructed based on some text dependency tables,
3384865Sobrien   which are also easier to maintain than the final representation.
3484865Sobrien
3584865Sobrien*/
3684865Sobrien
3784865Sobrien#include <stdio.h>
3884865Sobrien#include <ctype.h>
3984865Sobrien
4084865Sobrien#include "ansidecl.h"
4184865Sobrien#include "libiberty.h"
4284865Sobrien#include "sysdep.h"
4384865Sobrien#include "ia64-opc.h"
4484865Sobrien#include "ia64-opc-a.c"
4584865Sobrien#include "ia64-opc-i.c"
4684865Sobrien#include "ia64-opc-m.c"
4784865Sobrien#include "ia64-opc-b.c"
4884865Sobrien#include "ia64-opc-f.c"
4984865Sobrien#include "ia64-opc-x.c"
5084865Sobrien#include "ia64-opc-d.c"
5184865Sobrien
5284865Sobrienint debug = 0;
5384865Sobrien
5484865Sobrien#define tmalloc(X) (X *) xmalloc (sizeof (X))
5584865Sobrien
5684865Sobrien/* The main opcode table entry.  Each entry is a unique combination of
5784865Sobrien   name and flags (no two entries in the table compare as being equal
5884865Sobrien   via opcodes_eq). */
5984865Sobrienstruct main_entry
6084865Sobrien{
6184865Sobrien  /* The base name of this opcode.  The names of its completers are
6284865Sobrien     appended to it to generate the full instruction name. */
6384865Sobrien  struct string_entry *name;
6484865Sobrien  /* The base opcode entry.  Which one to use is a fairly arbitrary choice;
6584865Sobrien     it uses the first one passed to add_opcode_entry. */
6684865Sobrien  struct ia64_opcode *opcode;
6784865Sobrien  /* The list of completers that can be applied to this opcode. */
6884865Sobrien  struct completer_entry *completers;
6984865Sobrien  /* Next entry in the chain. */
7084865Sobrien  struct main_entry *next;
7184865Sobrien  /* Index in the  main table. */
7284865Sobrien  int main_index;
7384865Sobrien} *maintable, **ordered_table;
7484865Sobrienint otlen = 0;
7584865Sobrienint ottotlen = 0;
7684865Sobrienint opcode_count = 0;
7784865Sobrien
7884865Sobrien/* The set of possible completers for an opcode. */
7984865Sobrienstruct completer_entry
8084865Sobrien{
8184865Sobrien  /* This entry's index in the ia64_completer_table[] array. */
8284865Sobrien  int num;
8384865Sobrien
8484865Sobrien  /* The name of the completer. */
8584865Sobrien  struct string_entry *name;
8684865Sobrien
8784865Sobrien  /* This entry's parent. */
8884865Sobrien  struct completer_entry *parent;
8984865Sobrien
9084865Sobrien  /* Set if this is a terminal completer (occurs at the end of an
9184865Sobrien     opcode). */
9284865Sobrien  int is_terminal;
9384865Sobrien
9484865Sobrien  /* An alternative completer. */
9584865Sobrien  struct completer_entry *alternative;
9684865Sobrien
9784865Sobrien  /* Additional completers that can be appended to this one.  */
9884865Sobrien  struct completer_entry *addl_entries;
9984865Sobrien
10084865Sobrien  /* Before compute_completer_bits () is invoked, this contains the actual
10184865Sobrien     instruction opcode for this combination of opcode and completers.
10284865Sobrien     Afterwards, it contains those bits that are different from its
10384865Sobrien     parent opcode. */
10484865Sobrien  ia64_insn bits;
10584865Sobrien
10684865Sobrien  /* Bits set to 1 correspond to those bits in this completer's opcode
10784865Sobrien     that are different from its parent completer's opcode (or from
10884865Sobrien     the base opcode if the entry is the root of the opcode's completer
10984865Sobrien     list).  This field is filled in by compute_completer_bits (). */
11084865Sobrien  ia64_insn mask;
11184865Sobrien
11284865Sobrien  /* Index into the opcode dependency list, or -1 if none. */
11384865Sobrien  int dependencies;
11484865Sobrien
11584865Sobrien  /* Remember the order encountered in the opcode tables.  */
11684865Sobrien  int order;
11784865Sobrien};
11884865Sobrien
11984865Sobrien/* One entry in the disassembler name table. */
12084865Sobrienstruct disent
12184865Sobrien{
12284865Sobrien  /* The index into the ia64_name_dis array for this entry. */
12384865Sobrien  int ournum;
12484865Sobrien
12584865Sobrien  /* The index into the main_table[] array. */
12684865Sobrien  int insn;
12784865Sobrien
12884865Sobrien  /* The disassmbly priority of this entry. */
12984865Sobrien  int priority;
13084865Sobrien
13184865Sobrien  /* The completer_index value for this entry. */
13284865Sobrien  int completer_index;
13384865Sobrien
13484865Sobrien  /* How many other entries share this decode. */
13584865Sobrien  int nextcnt;
13684865Sobrien
13784865Sobrien  /* The next entry sharing the same decode. */
13884865Sobrien  struct disent *nexte;
13984865Sobrien
14084865Sobrien  /* The next entry in the name list. */
14184865Sobrien  struct disent *next_ent;
14284865Sobrien} *disinsntable = NULL;
14384865Sobrien
14484865Sobrien/* A state machine that will eventually be used to generate the
14584865Sobrien   disassembler table. */
14684865Sobrienstruct bittree
14784865Sobrien{
14884865Sobrien  struct disent *disent;
14984865Sobrien  struct bittree *bits[3]; /* 0, 1, and X (don't care) */
15084865Sobrien  int bits_to_skip;
15184865Sobrien  int skip_flag;
15284865Sobrien} *bittree;
15384865Sobrien
15484865Sobrien/* The string table contains all opcodes and completers sorted in
15584865Sobrien   alphabetical order.  */
15684865Sobrien
15784865Sobrien/* One entry in the string table. */
15884865Sobrienstruct string_entry
15984865Sobrien{
16084865Sobrien  /* The index in the ia64_strings[] array for this entry. */
16184865Sobrien  int num;
16284865Sobrien  /* And the string. */
16384865Sobrien  char *s;
16484865Sobrien} **string_table = NULL;
16584865Sobrienint strtablen = 0;
16684865Sobrienint strtabtotlen = 0;
16784865Sobrien
16884865Sobrien
16984865Sobrien/* resource dependency entries */
17084865Sobrienstruct rdep
17184865Sobrien{
17284865Sobrien  char *name;                       /* resource name */
17384865Sobrien  unsigned
17484865Sobrien    mode:2,                         /* RAW, WAW, or WAR */
17584865Sobrien    semantics:3;                    /* dependency semantics */
17684865Sobrien  char *extra;                      /* additional semantics info */
17784865Sobrien  int nchks;
17884865Sobrien  int total_chks;                   /* total #of terminal insns */
17984865Sobrien  int *chks;                        /* insn classes which read (RAW), write
18084865Sobrien                                       (WAW), or write (WAR) this rsrc */
18184865Sobrien  int *chknotes;                    /* dependency notes for each class */
18284865Sobrien  int nregs;
18384865Sobrien  int total_regs;                   /* total #of terminal insns */
18484865Sobrien  int *regs;                        /* insn class which write (RAW), write2
18584865Sobrien                                       (WAW), or read (WAR) this rsrc */
18684865Sobrien  int *regnotes;                    /* dependency notes for each class */
18784865Sobrien
18884865Sobrien  int waw_special;                  /* special WAW dependency note */
18984865Sobrien} **rdeps = NULL;
19084865Sobrien
19184865Sobrienstatic int rdepslen = 0;
19284865Sobrienstatic int rdepstotlen = 0;
19384865Sobrien
19484865Sobrien/* array of all instruction classes */
19584865Sobrienstruct iclass
19684865Sobrien{
19784865Sobrien  char *name;                       /* instruction class name */
19884865Sobrien  int is_class;                     /* is a class, not a terminal */
19984865Sobrien  int nsubs;
20084865Sobrien  int *subs;                        /* other classes within this class */
20184865Sobrien  int nxsubs;
20284865Sobrien  int xsubs[4];                     /* exclusions */
20384865Sobrien  char *comment;                    /* optional comment */
20484865Sobrien  int note;                         /* optional note */
20584865Sobrien  int terminal_resolved;            /* did we match this with anything? */
20684865Sobrien  int orphan;                       /* detect class orphans */
20784865Sobrien} **ics = NULL;
20884865Sobrien
20984865Sobrienstatic int iclen = 0;
21084865Sobrienstatic int ictotlen = 0;
21184865Sobrien
21284865Sobrien/* an opcode dependency (chk/reg pair of dependency lists) */
21384865Sobrienstruct opdep
21484865Sobrien{
21584865Sobrien  int chk;                          /* index into dlists */
21684865Sobrien  int reg;                          /* index into dlists */
21784865Sobrien} **opdeps;
21884865Sobrien
21984865Sobrienstatic int opdeplen = 0;
22084865Sobrienstatic int opdeptotlen = 0;
22184865Sobrien
22284865Sobrien/* a generic list of dependencies w/notes encoded.  these may be shared. */
22384865Sobrienstruct deplist
22484865Sobrien{
22584865Sobrien  int len;
22684865Sobrien  unsigned short *deps;
22784865Sobrien} **dlists;
22884865Sobrien
22984865Sobrienstatic int dlistlen = 0;
23084865Sobrienstatic int dlisttotlen = 0;
23184865Sobrien
23284865Sobrien/* add NAME to the resource table, where TYPE is RAW or WAW */
23384865Sobrienstatic struct rdep *
23484865Sobrieninsert_resource (const char *name, enum ia64_dependency_mode type)
23584865Sobrien{
23684865Sobrien  if (rdepslen == rdepstotlen)
23784865Sobrien    {
23884865Sobrien      rdepstotlen += 20;
23984865Sobrien      rdeps = (struct rdep **)
24084865Sobrien        xrealloc (rdeps, sizeof(struct rdep **) * rdepstotlen);
24184865Sobrien    }
24284865Sobrien  rdeps[rdepslen] = tmalloc(struct rdep);
24384865Sobrien  memset((void *)rdeps[rdepslen], 0, sizeof(struct rdep));
24484865Sobrien  rdeps[rdepslen]->name = xstrdup (name);
24584865Sobrien  rdeps[rdepslen]->mode = type;
24684865Sobrien  rdeps[rdepslen]->waw_special = 0;
24784865Sobrien
24884865Sobrien  return rdeps[rdepslen++];
24984865Sobrien}
25084865Sobrien
25184865Sobrien/* are the lists of dependency indexes equivalent? */
25284865Sobrienstatic int
25384865Sobriendeplist_equals (struct deplist *d1, struct deplist *d2)
25484865Sobrien{
25584865Sobrien  int i;
25684865Sobrien
25784865Sobrien  if (d1->len != d2->len)
25884865Sobrien    return 0;
25984865Sobrien
26084865Sobrien  for (i=0;i < d1->len;i++)
26184865Sobrien    {
26284865Sobrien      if (d1->deps[i] != d2->deps[i])
26384865Sobrien        return 0;
26484865Sobrien    }
26584865Sobrien
26684865Sobrien  return 1;
26784865Sobrien}
26884865Sobrien
26984865Sobrien/* add the list of dependencies to the list of dependency lists */
27084865Sobrienstatic short
27184865Sobrieninsert_deplist(int count, unsigned short *deps)
27284865Sobrien{
27384865Sobrien  /* sort the list, then see if an equivalent list exists already.
27484865Sobrien     this results in a much smaller set of dependency lists
27584865Sobrien   */
27684865Sobrien  struct deplist *list;
27784865Sobrien  char set[0x10000];
27884865Sobrien  int i;
27984865Sobrien
28084865Sobrien  memset ((void *)set, 0, sizeof(set));
28184865Sobrien  for (i=0;i < count;i++)
28284865Sobrien    set[deps[i]] = 1;
28384865Sobrien  count = 0;
28484865Sobrien  for (i=0;i < (int)sizeof(set);i++)
28584865Sobrien    if (set[i])
28684865Sobrien      ++count;
28784865Sobrien
28884865Sobrien  list = tmalloc(struct deplist);
28984865Sobrien  list->len = count;
29084865Sobrien  list->deps = (unsigned short *)malloc (sizeof(unsigned short) * count);
29184865Sobrien  for (i=0, count=0;i < (int)sizeof(set);i++)
29284865Sobrien    {
29384865Sobrien      if (set[i])
29484865Sobrien        {
29584865Sobrien          list->deps[count++] = i;
29684865Sobrien        }
29784865Sobrien    }
29884865Sobrien
29984865Sobrien  /* does this list exist already? */
30084865Sobrien  for (i=0;i < dlistlen;i++)
30184865Sobrien    {
30284865Sobrien      if (deplist_equals (list, dlists[i]))
30384865Sobrien        {
30484865Sobrien          free (list->deps);
30584865Sobrien          free (list);
30684865Sobrien          return i;
30784865Sobrien        }
30884865Sobrien    }
30984865Sobrien
31084865Sobrien  if (dlistlen == dlisttotlen)
31184865Sobrien    {
31284865Sobrien      dlisttotlen += 20;
31384865Sobrien      dlists = (struct deplist **)
31484865Sobrien        xrealloc (dlists, sizeof(struct deplist **) * dlisttotlen);
31584865Sobrien    }
31684865Sobrien  dlists[dlistlen] = list;
31784865Sobrien
31884865Sobrien  return dlistlen++;
31984865Sobrien}
32084865Sobrien
32184865Sobrien/* add the given pair of dependency lists to the opcode dependency list */
32284865Sobrienstatic short
32384865Sobrieninsert_dependencies (int nchks, unsigned short *chks,
32484865Sobrien                     int nregs, unsigned short *regs)
32584865Sobrien{
32684865Sobrien  struct opdep *pair;
32784865Sobrien  int i;
32884865Sobrien  int regind = -1;
32984865Sobrien  int chkind = -1;
33084865Sobrien
33184865Sobrien  if (nregs > 0)
33284865Sobrien    regind = insert_deplist (nregs, regs);
33384865Sobrien  if (nchks > 0)
33484865Sobrien    chkind = insert_deplist (nchks, chks);
33584865Sobrien
33684865Sobrien  for (i=0;i < opdeplen;i++)
33784865Sobrien    {
33884865Sobrien      if (opdeps[i]->chk == chkind
33984865Sobrien          && opdeps[i]->reg == regind)
34084865Sobrien        return i;
34184865Sobrien    }
34284865Sobrien  pair = tmalloc(struct opdep);
34384865Sobrien  pair->chk = chkind;
34484865Sobrien  pair->reg = regind;
34584865Sobrien
34684865Sobrien  if (opdeplen == opdeptotlen)
34784865Sobrien    {
34884865Sobrien      opdeptotlen += 20;
34984865Sobrien      opdeps = (struct opdep **)
35084865Sobrien        xrealloc (opdeps, sizeof(struct opdep **) * opdeptotlen);
35184865Sobrien    }
35284865Sobrien  opdeps[opdeplen] = pair;
35384865Sobrien
35484865Sobrien  return opdeplen++;
35584865Sobrien}
35684865Sobrien
35784865Sobrienstatic void
35884865Sobrienmark_used (struct iclass *ic, int clear_terminals)
35984865Sobrien{
36084865Sobrien  int i;
36184865Sobrien
36284865Sobrien  ic->orphan = 0;
36384865Sobrien  if (clear_terminals)
36484865Sobrien    ic->terminal_resolved = 1;
36584865Sobrien
36684865Sobrien  for (i=0;i < ic->nsubs;i++)
36784865Sobrien    {
36884865Sobrien      mark_used (ics[ic->subs[i]], clear_terminals);
36984865Sobrien    }
37084865Sobrien  for (i=0;i < ic->nxsubs;i++)
37184865Sobrien    {
37284865Sobrien      mark_used (ics[ic->xsubs[i]], clear_terminals);
37384865Sobrien    }
37484865Sobrien}
37584865Sobrien
37684865Sobrien/* look up an instruction class; if CREATE make a new one if none found;
37784865Sobrien   returns the index into the insn class array */
37884865Sobrienstatic int
37984865Sobrienfetch_insn_class(const char *full_name, int create)
38084865Sobrien{
38184865Sobrien  char *name;
38284865Sobrien  char *notestr;
38384865Sobrien  char *xsect;
38484865Sobrien  char *comment;
38584865Sobrien  int i, note = 0;
38684865Sobrien  int ind;
38784865Sobrien  int is_class = 0;
38884865Sobrien
38984865Sobrien  if (strncmp (full_name, "IC:", 3) == 0)
39084865Sobrien    {
39184865Sobrien      name = xstrdup (full_name + 3);
39284865Sobrien      is_class = 1;
39384865Sobrien    }
39484865Sobrien  else
39584865Sobrien    name = xstrdup (full_name);
39684865Sobrien
39784865Sobrien  if ((xsect = strchr(name, '\\')) != NULL)
39884865Sobrien    is_class = 1;
39984865Sobrien  if ((comment = strchr(name, '[')) != NULL)
40084865Sobrien    is_class = 1;
40184865Sobrien  if ((notestr = strchr(name, '+')) != NULL)
40284865Sobrien    is_class = 1;
40384865Sobrien
40484865Sobrien  /* If it is a composite class, then ignore comments and notes that come after
40584865Sobrien     the '\\', since they don't apply to the part we are decoding now.  */
40684865Sobrien  if (xsect)
40784865Sobrien    {
40884865Sobrien      if (comment > xsect)
40984865Sobrien	comment = 0;
41084865Sobrien      if (notestr > xsect)
41184865Sobrien	notestr = 0;
41284865Sobrien    }
41384865Sobrien
41484865Sobrien  if (notestr)
41584865Sobrien    {
41684865Sobrien      char *nextnotestr;
41784865Sobrien      note = atoi (notestr + 1);
41884865Sobrien      if ((nextnotestr = strchr (notestr + 1, '+')) != NULL)
41984865Sobrien        {
42084865Sobrien          if (strcmp (notestr, "+1+13") == 0)
42184865Sobrien            note = 13;
42284865Sobrien          else if (!xsect || nextnotestr < xsect)
42384865Sobrien            fprintf (stderr, "Warning: multiple note %s not handled\n",
42484865Sobrien                     notestr);
42584865Sobrien        }
42684865Sobrien    }
42784865Sobrien
42884865Sobrien  /* If it's a composite class, leave the notes and comments in place so that
42984865Sobrien     we have a unique name for the composite class.  Otherwise, we remove
43084865Sobrien     them.  */
43184865Sobrien  if (!xsect)
43284865Sobrien    {
43384865Sobrien      if (notestr)
43484865Sobrien        *notestr = 0;
43584865Sobrien      if (comment)
43684865Sobrien        *comment = 0;
43784865Sobrien    }
43884865Sobrien
43984865Sobrien  for (i=0;i < iclen;i++)
44084865Sobrien    if (strcmp(name, ics[i]->name) == 0
44184865Sobrien        && ((comment == NULL && ics[i]->comment == NULL)
44284865Sobrien            || (comment != NULL && ics[i]->comment != NULL
44384865Sobrien                && strncmp (ics[i]->comment, comment,
44484865Sobrien                            strlen (ics[i]->comment)) == 0))
44584865Sobrien        && note == ics[i]->note)
44684865Sobrien      return i;
44784865Sobrien
44884865Sobrien  if (!create)
44984865Sobrien    return -1;
45084865Sobrien
45184865Sobrien  /* doesn't exist, so make a new one */
45284865Sobrien  if (iclen == ictotlen)
45384865Sobrien    {
45484865Sobrien      ictotlen += 20;
45584865Sobrien      ics = (struct iclass **)
45684865Sobrien        xrealloc(ics, (ictotlen)*sizeof(struct iclass *));
45784865Sobrien    }
45884865Sobrien  ind = iclen++;
45984865Sobrien  ics[ind] = tmalloc(struct iclass);
46084865Sobrien  memset((void *)ics[ind], 0, sizeof(struct iclass));
46184865Sobrien  ics[ind]->name = xstrdup(name);
46284865Sobrien  ics[ind]->is_class = is_class;
46384865Sobrien  ics[ind]->orphan = 1;
46484865Sobrien
46584865Sobrien  if (comment)
46684865Sobrien    {
46784865Sobrien      ics[ind]->comment = xstrdup (comment + 1);
46884865Sobrien      ics[ind]->comment[strlen(ics[ind]->comment)-1] = 0;
46984865Sobrien    }
47084865Sobrien  if (notestr)
47184865Sobrien    ics[ind]->note = note;
47284865Sobrien
47384865Sobrien  /* if it's a composite class, there's a comment or note, look for an
47484865Sobrien     existing class or terminal with the same name. */
47584865Sobrien  if ((xsect || comment || notestr) && is_class)
47684865Sobrien    {
47784865Sobrien      /* First, populate with the class we're based on.  */
47884865Sobrien      char *subname = name;
47984865Sobrien      if (xsect)
48084865Sobrien        *xsect = 0;
48184865Sobrien      else if (comment)
48284865Sobrien        *comment = 0;
48384865Sobrien      else if (notestr)
48484865Sobrien        *notestr = 0;
48584865Sobrien      ics[ind]->nsubs = 1;
48684865Sobrien      ics[ind]->subs = tmalloc(int);
48784865Sobrien      ics[ind]->subs[0] = fetch_insn_class (subname, 1);;
48884865Sobrien    }
48984865Sobrien
49084865Sobrien  while (xsect)
49184865Sobrien    {
49284865Sobrien      char *subname = xsect + 1;
49384865Sobrien      xsect = strchr (subname, '\\');
49484865Sobrien      if (xsect)
49584865Sobrien        *xsect = 0;
49684865Sobrien      ics[ind]->xsubs[ics[ind]->nxsubs] = fetch_insn_class (subname,1);
49784865Sobrien      ics[ind]->nxsubs++;
49884865Sobrien    }
49984865Sobrien  free (name);
50084865Sobrien
50184865Sobrien  return ind;
50284865Sobrien}
50384865Sobrien
50484865Sobrien/* for sorting a class's sub-class list only; make sure classes appear before
50584865Sobrien   terminals  */
50684865Sobrienstatic int
50784865Sobriensub_compare (const void *e1, const void *e2)
50884865Sobrien{
50984865Sobrien  struct iclass *ic1 = ics[*(int *)e1];
51084865Sobrien  struct iclass *ic2 = ics[*(int *)e2];
51184865Sobrien
51284865Sobrien  if (ic1->is_class)
51384865Sobrien    {
51484865Sobrien      if (!ic2->is_class)
51584865Sobrien        return -1;
51684865Sobrien    }
51784865Sobrien  else if (ic2->is_class)
51884865Sobrien    return 1;
51984865Sobrien
52084865Sobrien  return strcmp (ic1->name, ic2->name);
52184865Sobrien}
52284865Sobrien
52384865Sobrienstatic void
52484865Sobrienload_insn_classes()
52584865Sobrien{
52684865Sobrien  FILE *fp = fopen("ia64-ic.tbl", "r");
52784865Sobrien  char buf[2048];
52884865Sobrien
52984865Sobrien  if (fp == NULL){
53084865Sobrien    fprintf (stderr, "Can't find ia64-ic.tbl for reading\n");
53184865Sobrien    exit(1);
53284865Sobrien  }
53384865Sobrien
53484865Sobrien  /* discard first line */
53584865Sobrien  fgets (buf, sizeof(buf), fp);
53684865Sobrien
53784865Sobrien  while (!feof(fp))
53884865Sobrien    {
53984865Sobrien      int iclass;
54084865Sobrien      char *name;
54184865Sobrien      char *tmp;
54284865Sobrien
54384865Sobrien      if (fgets (buf, sizeof(buf), fp) == NULL)
54484865Sobrien        break;
54584865Sobrien
54684865Sobrien      while (isspace(buf[strlen(buf)-1]))
54784865Sobrien        buf[strlen(buf)-1] = '\0';
54884865Sobrien
54984865Sobrien      name = tmp = buf;
55084865Sobrien      while (*tmp != ';')
55184865Sobrien        {
55284865Sobrien          ++tmp;
55384865Sobrien          if (tmp == buf + sizeof(buf))
55484865Sobrien            abort ();
55584865Sobrien        }
55684865Sobrien      *tmp++ = '\0';
55784865Sobrien
55884865Sobrien      iclass = fetch_insn_class(name, 1);
55984865Sobrien      ics[iclass]->is_class = 1;
56084865Sobrien
56184865Sobrien      if (strcmp (name, "none") == 0)
56284865Sobrien        {
56384865Sobrien          ics[iclass]->is_class = 0;
56484865Sobrien          ics[iclass]->terminal_resolved = 1;
56584865Sobrien          continue;
56684865Sobrien        }
56784865Sobrien
56884865Sobrien      /* for this class, record all sub-classes */
56984865Sobrien      while (*tmp)
57084865Sobrien        {
57184865Sobrien          char *subname;
57284865Sobrien          int sub;
57384865Sobrien
57484865Sobrien          while (*tmp && isspace(*tmp))
57584865Sobrien            {
57684865Sobrien              ++tmp;
57784865Sobrien              if (tmp == buf + sizeof(buf))
57884865Sobrien                abort();
57984865Sobrien            }
58084865Sobrien          subname = tmp;
58184865Sobrien          while (*tmp && *tmp != ',')
58284865Sobrien            {
58384865Sobrien              ++tmp;
58484865Sobrien              if (tmp == buf + sizeof(buf))
58584865Sobrien                abort();
58684865Sobrien            }
58784865Sobrien          if (*tmp == ',')
58884865Sobrien            *tmp++ = '\0';
58984865Sobrien
59084865Sobrien          ics[iclass]->subs = (int *)
59184865Sobrien            xrealloc((void *)ics[iclass]->subs,
59284865Sobrien                     (ics[iclass]->nsubs+1)*sizeof(int));
59384865Sobrien
59484865Sobrien          sub = fetch_insn_class(subname, 1);
59584865Sobrien          ics[iclass]->subs = (int *)
59684865Sobrien            xrealloc(ics[iclass]->subs, (ics[iclass]->nsubs+1)*sizeof(int));
59784865Sobrien          ics[iclass]->subs[ics[iclass]->nsubs++] = sub;
59884865Sobrien        }
59984865Sobrien      /* make sure classes come before terminals */
60084865Sobrien      qsort ((void *)ics[iclass]->subs,
60184865Sobrien             ics[iclass]->nsubs, sizeof(int), sub_compare);
60284865Sobrien    }
60384865Sobrien  fclose(fp);
60484865Sobrien
60584865Sobrien  if (debug)
60684865Sobrien    {
60784865Sobrien      printf ("%d classes\n", iclen);
60884865Sobrien    }
60984865Sobrien}
61084865Sobrien
61184865Sobrien/* extract the insn classes from the given line */
61284865Sobrienstatic void
61384865Sobrienparse_resource_users(ref, usersp, nusersp, notesp)
61484865Sobrien  char *ref;
61584865Sobrien  int **usersp;
61684865Sobrien  int *nusersp;
61784865Sobrien  int **notesp;
61884865Sobrien{
61984865Sobrien  int c;
62084865Sobrien  char *line = xstrdup (ref);
62184865Sobrien  char *tmp = line;
62284865Sobrien  int *users = *usersp;
62384865Sobrien  int count = *nusersp;
62484865Sobrien  int *notes = *notesp;
62584865Sobrien
62684865Sobrien  c = *tmp;
62784865Sobrien  while (c != 0)
62884865Sobrien    {
62984865Sobrien      char *notestr;
63084865Sobrien      int note;
63184865Sobrien      char *xsect;
63284865Sobrien      int iclass;
63384865Sobrien      int create = 0;
63484865Sobrien      char *name;
63584865Sobrien
63684865Sobrien      while (isspace(*tmp))
63784865Sobrien        ++tmp;
63884865Sobrien      name = tmp;
63984865Sobrien      while (*tmp && *tmp != ',')
64084865Sobrien        ++tmp;
64184865Sobrien      c = *tmp;
64284865Sobrien      *tmp++ = '\0';
64384865Sobrien
64484865Sobrien      xsect = strchr(name, '\\');
64584865Sobrien      if ((notestr = strstr(name, "+")) != NULL)
64684865Sobrien        {
64784865Sobrien          char *nextnotestr;
64884865Sobrien          note = atoi (notestr + 1);
64984865Sobrien          if ((nextnotestr = strchr (notestr + 1, '+')) != NULL)
65084865Sobrien            {
65184865Sobrien              /* note 13 always implies note 1 */
65284865Sobrien              if (strcmp (notestr, "+1+13") == 0)
65384865Sobrien                note = 13;
65484865Sobrien              else if (!xsect || nextnotestr < xsect)
65584865Sobrien                fprintf (stderr, "Warning: multiple note %s not handled\n",
65684865Sobrien                         notestr);
65784865Sobrien            }
65884865Sobrien          if (!xsect)
65984865Sobrien            *notestr = '\0';
66084865Sobrien        }
66184865Sobrien      else
66284865Sobrien        note = 0;
66384865Sobrien
66484865Sobrien      /* All classes are created when the insn class table is parsed;
66584865Sobrien         Individual instructions might not appear until the dependency tables
66684865Sobrien         are read.  Only create new classes if it's *not* an insn class,
66784865Sobrien         or if it's a composite class (which wouldn't necessarily be in the IC
66884865Sobrien         table).
66984865Sobrien      */
67084865Sobrien      if (strncmp(name, "IC:", 3) != 0 || xsect != NULL)
67184865Sobrien        create = 1;
67284865Sobrien
67384865Sobrien      iclass = fetch_insn_class(name, create);
67484865Sobrien      if (iclass != -1)
67584865Sobrien        {
67684865Sobrien          users = (int *)
67784865Sobrien            xrealloc ((void *)users,(count+1)*sizeof(int));
67884865Sobrien          notes = (int *)
67984865Sobrien            xrealloc ((void *)notes,(count+1)*sizeof(int));
68084865Sobrien          notes[count] = note;
68184865Sobrien          users[count++] = iclass;
68284865Sobrien          mark_used (ics[iclass], 0);
68384865Sobrien        }
68484865Sobrien      else
68584865Sobrien        {
68684865Sobrien          if (debug)
68784865Sobrien            printf("Class %s not found\n", name);
68884865Sobrien        }
68984865Sobrien    }
69084865Sobrien  /* update the return values */
69184865Sobrien  *usersp = users;
69284865Sobrien  *nusersp = count;
69384865Sobrien  *notesp = notes;
69484865Sobrien
69584865Sobrien  free (line);
69684865Sobrien}
69784865Sobrien
69884865Sobrienstatic int
69984865Sobrienparse_semantics (char *sem)
70084865Sobrien{
70184865Sobrien  if (strcmp (sem, "none") == 0)
70284865Sobrien    return IA64_DVS_NONE;
70384865Sobrien  else if (strcmp (sem, "implied") == 0)
70484865Sobrien    return IA64_DVS_IMPLIED;
70584865Sobrien  else if (strcmp (sem, "impliedF") == 0)
70684865Sobrien    return IA64_DVS_IMPLIEDF;
70784865Sobrien  else if (strcmp (sem, "data") == 0)
70884865Sobrien    return IA64_DVS_DATA;
70984865Sobrien  else if (strcmp (sem, "instr") == 0)
71084865Sobrien    return IA64_DVS_INSTR;
71184865Sobrien  else if (strcmp (sem, "specific") == 0)
71284865Sobrien    return IA64_DVS_SPECIFIC;
71384865Sobrien  else if (strcmp (sem, "stop") == 0)
71484865Sobrien    return IA64_DVS_STOP;
71584865Sobrien  else
71684865Sobrien    return IA64_DVS_OTHER;
71784865Sobrien}
71884865Sobrien
71984865Sobrienstatic void
72084865Sobrienadd_dep (const char *name, const char *chk, const char *reg,
72184865Sobrien         int semantics, int mode, char *extra, int flag)
72284865Sobrien{
72384865Sobrien  struct rdep *rs;
72484865Sobrien
72584865Sobrien  rs = insert_resource (name, mode);
72684865Sobrien  parse_resource_users (chk, &rs->chks, &rs->nchks,
72784865Sobrien                        &rs->chknotes);
72884865Sobrien  parse_resource_users (reg, &rs->regs, &rs->nregs,
72984865Sobrien                        &rs->regnotes);
73084865Sobrien  rs->semantics = semantics;
73184865Sobrien  rs->extra = extra;
73284865Sobrien  rs->waw_special = flag;
73384865Sobrien}
73484865Sobrien
73584865Sobrienstatic void
73684865Sobrienload_depfile (const char *filename, enum ia64_dependency_mode mode)
73784865Sobrien{
73884865Sobrien  FILE *fp = fopen(filename, "r");
73984865Sobrien  char buf[1024];
74084865Sobrien
74184865Sobrien  if (fp == NULL){
74284865Sobrien    fprintf (stderr, "Can't find %s for reading\n", filename);
74384865Sobrien    exit(1);
74484865Sobrien  }
74584865Sobrien
74684865Sobrien  fgets(buf, sizeof(buf), fp);
74784865Sobrien  while (!feof(fp))
74884865Sobrien    {
74984865Sobrien      char *name, *tmp;
75084865Sobrien      int semantics;
75184865Sobrien      char *extra;
75284865Sobrien      char *regp, *chkp;
75384865Sobrien
75484865Sobrien      if (fgets (buf, sizeof(buf), fp) == NULL)
75584865Sobrien        break;
75684865Sobrien
75784865Sobrien      while (isspace(buf[strlen(buf)-1]))
75884865Sobrien        buf[strlen(buf)-1] = '\0';
75984865Sobrien
76084865Sobrien      name = tmp = buf;
76184865Sobrien      while (*tmp != ';')
76284865Sobrien        ++tmp;
76384865Sobrien      *tmp++ = '\0';
76484865Sobrien
76584865Sobrien      while (isspace (*tmp))
76684865Sobrien        ++tmp;
76784865Sobrien      regp = tmp;
76884865Sobrien      tmp = strchr (tmp, ';');
76984865Sobrien      if (!tmp)
77084865Sobrien        abort ();
77184865Sobrien      *tmp++ = 0;
77284865Sobrien      while (isspace (*tmp))
77384865Sobrien        ++tmp;
77484865Sobrien      chkp = tmp;
77584865Sobrien      tmp = strchr (tmp, ';');
77684865Sobrien      if (!tmp)
77784865Sobrien        abort ();
77884865Sobrien      *tmp++ = 0;
77984865Sobrien      while (isspace (*tmp))
78084865Sobrien        ++tmp;
78184865Sobrien      semantics = parse_semantics (tmp);
78284865Sobrien      extra = semantics == IA64_DVS_OTHER ? xstrdup (tmp) : NULL;
78384865Sobrien
78484865Sobrien      /* For WAW entries, if the chks and regs differ, we need to enter the
78584865Sobrien         entries in both positions so that the tables will be parsed properly,
78684865Sobrien         without a lot of extra work */
78784865Sobrien      if (mode == IA64_DV_WAW && strcmp (regp, chkp) != 0)
78884865Sobrien        {
78984865Sobrien          add_dep (name, chkp, regp, semantics, mode, extra, 0);
79084865Sobrien          add_dep (name, regp, chkp, semantics, mode, extra, 1);
79184865Sobrien        }
79284865Sobrien      else
79384865Sobrien        {
79484865Sobrien          add_dep (name, chkp, regp, semantics, mode, extra, 0);
79584865Sobrien        }
79684865Sobrien    }
79784865Sobrien  fclose(fp);
79884865Sobrien}
79984865Sobrien
80084865Sobrienstatic void
80184865Sobrienload_dependencies()
80284865Sobrien{
80384865Sobrien  load_depfile ("ia64-raw.tbl", IA64_DV_RAW);
80484865Sobrien  load_depfile ("ia64-waw.tbl", IA64_DV_WAW);
80584865Sobrien  load_depfile ("ia64-war.tbl", IA64_DV_WAR);
80684865Sobrien
80784865Sobrien  if (debug)
80884865Sobrien      printf ("%d RAW/WAW/WAR dependencies\n", rdepslen);
80984865Sobrien}
81084865Sobrien
81184865Sobrien/* is the given operand an indirect register file operand? */
81284865Sobrienstatic int
81384865Sobrienirf_operand (int op, const char *field)
81484865Sobrien{
81584865Sobrien  if (!field)
81684865Sobrien    {
81784865Sobrien      return op == IA64_OPND_RR_R3 || op == IA64_OPND_DBR_R3
81884865Sobrien        || op == IA64_OPND_IBR_R3  || op == IA64_OPND_PKR_R3
81984865Sobrien	|| op == IA64_OPND_PMC_R3  || op == IA64_OPND_PMD_R3
82084865Sobrien	|| op == IA64_OPND_MSR_R3 || op == IA64_OPND_CPUID_R3;
82184865Sobrien    }
82284865Sobrien  else
82384865Sobrien    {
82484865Sobrien      return ((op == IA64_OPND_RR_R3 && strstr (field, "rr"))
82584865Sobrien              || (op == IA64_OPND_DBR_R3 && strstr (field, "dbr"))
82684865Sobrien              || (op == IA64_OPND_IBR_R3 && strstr (field, "ibr"))
82784865Sobrien              || (op == IA64_OPND_PKR_R3 && strstr (field, "pkr"))
82884865Sobrien              || (op == IA64_OPND_PMC_R3 && strstr (field, "pmc"))
82984865Sobrien              || (op == IA64_OPND_PMD_R3 && strstr (field, "pmd"))
83084865Sobrien              || (op == IA64_OPND_MSR_R3 && strstr (field, "msr"))
83184865Sobrien              || (op == IA64_OPND_CPUID_R3 && strstr (field, "cpuid")));
83284865Sobrien    }
83384865Sobrien}
83484865Sobrien
83584865Sobrien/* handle mov_ar, mov_br, mov_cr, mov_indirect, mov_ip, mov_pr, mov_psr, and
83684865Sobrien   mov_um insn classes */
83784865Sobrienstatic int
83884865Sobrienin_iclass_mov_x (struct ia64_opcode *idesc, struct iclass *ic,
83984865Sobrien                 const char *format, const char *field)
84084865Sobrien{
84184865Sobrien  int plain_mov = strcmp (idesc->name, "mov") == 0;
84284865Sobrien
84384865Sobrien  if (!format)
84484865Sobrien    return 0;
84584865Sobrien
84684865Sobrien  switch (ic->name[4])
84784865Sobrien    {
84884865Sobrien    default:
84984865Sobrien      abort ();
85084865Sobrien    case 'a':
85184865Sobrien      {
85284865Sobrien        int i = strcmp (idesc->name, "mov.i") == 0;
85384865Sobrien        int m = strcmp (idesc->name, "mov.m") == 0;
85484865Sobrien        int i2627 = i && idesc->operands[0] == IA64_OPND_AR3;
85584865Sobrien        int i28 = i && idesc->operands[1] == IA64_OPND_AR3;
85684865Sobrien        int m2930 = m && idesc->operands[0] == IA64_OPND_AR3;
85784865Sobrien        int m31 = m && idesc->operands[1] == IA64_OPND_AR3;
85884865Sobrien        int pseudo0 = plain_mov && idesc->operands[1] == IA64_OPND_AR3;
85984865Sobrien        int pseudo1 = plain_mov && idesc->operands[0] == IA64_OPND_AR3;
86084865Sobrien
86184865Sobrien        /* IC:mov ar */
86284865Sobrien        if (i2627)
86384865Sobrien          return strstr (format, "I26") || strstr (format, "I27");
86484865Sobrien        if (i28)
86584865Sobrien          return strstr (format, "I28") != NULL;
86684865Sobrien        if (m2930)
86784865Sobrien          return strstr (format, "M29") || strstr (format, "M30");
86884865Sobrien        if (m31)
86984865Sobrien          return strstr (format, "M31") != NULL;
87084865Sobrien        if (pseudo0 || pseudo1)
87184865Sobrien          return 1;
87284865Sobrien      }
87384865Sobrien      break;
87484865Sobrien    case 'b':
87584865Sobrien      {
87684865Sobrien        int i21 = idesc->operands[0] == IA64_OPND_B1;
87784865Sobrien        int i22 = plain_mov && idesc->operands[1] == IA64_OPND_B2;
87884865Sobrien        if (i22)
87984865Sobrien          return strstr (format, "I22") != NULL;
88084865Sobrien        if (i21)
88184865Sobrien          return strstr (format, "I21") != NULL;
88284865Sobrien      }
88384865Sobrien      break;
88484865Sobrien    case 'c':
88584865Sobrien      {
88684865Sobrien        int m32 = plain_mov && idesc->operands[0] == IA64_OPND_CR3;
88784865Sobrien        int m33 = plain_mov && idesc->operands[1] == IA64_OPND_CR3;
88884865Sobrien        if (m32)
88984865Sobrien          return strstr (format, "M32") != NULL;
89084865Sobrien        if (m33)
89184865Sobrien          return strstr (format, "M33") != NULL;
89284865Sobrien      }
89384865Sobrien      break;
89484865Sobrien    case 'i':
89584865Sobrien      if (ic->name[5] == 'n')
89684865Sobrien        {
89784865Sobrien          int m42 = plain_mov && irf_operand (idesc->operands[0], field);
89884865Sobrien          int m43 = plain_mov && irf_operand (idesc->operands[1], field);
89984865Sobrien          if (m42)
90084865Sobrien            return strstr (format, "M42") != NULL;
90184865Sobrien          if (m43)
90284865Sobrien            return strstr (format, "M43") != NULL;
90384865Sobrien        }
90484865Sobrien      else if (ic->name[5] == 'p')
90584865Sobrien        {
90684865Sobrien          return idesc->operands[1] == IA64_OPND_IP;
90784865Sobrien        }
90884865Sobrien      else
90984865Sobrien        abort ();
91084865Sobrien      break;
91184865Sobrien    case 'p':
91284865Sobrien      if (ic->name[5] == 'r')
91384865Sobrien        {
91484865Sobrien          int i25 = plain_mov && idesc->operands[1] == IA64_OPND_PR;
91584865Sobrien          int i23 = plain_mov && idesc->operands[0] == IA64_OPND_PR;
91684865Sobrien          int i24 = plain_mov && idesc->operands[0] == IA64_OPND_PR_ROT;
91784865Sobrien          if (i23)
91884865Sobrien            return strstr (format, "I23") != NULL;
91984865Sobrien          if (i24)
92084865Sobrien            return strstr (format, "I24") != NULL;
92184865Sobrien          if (i25)
92284865Sobrien            return strstr (format, "I25") != NULL;
92384865Sobrien        }
92484865Sobrien      else if (ic->name[5] == 's')
92584865Sobrien        {
92684865Sobrien          int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_L;
92784865Sobrien          int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR;
92884865Sobrien          if (m35)
92984865Sobrien            return strstr (format, "M35") != NULL;
93084865Sobrien          if (m36)
93184865Sobrien            return strstr (format, "M36") != NULL;
93284865Sobrien        }
93384865Sobrien      else
93484865Sobrien        abort ();
93584865Sobrien      break;
93684865Sobrien    case 'u':
93784865Sobrien      {
93884865Sobrien        int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_UM;
93984865Sobrien        int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR_UM;
94084865Sobrien        if (m35)
94184865Sobrien          return strstr (format, "M35") != NULL;
94284865Sobrien        if (m36)
94384865Sobrien          return strstr (format, "M36") != NULL;
94484865Sobrien      }
94584865Sobrien      break;
94684865Sobrien    }
94784865Sobrien  return 0;
94884865Sobrien}
94984865Sobrien
95084865Sobrien
95184865Sobrien/* is the given opcode in the given insn class? */
95284865Sobrienstatic int
95384865Sobrienin_iclass(struct ia64_opcode *idesc, struct iclass *ic,
95484865Sobrien          const char *format, const char *field, int *notep)
95584865Sobrien{
95684865Sobrien  int i;
95784865Sobrien  int resolved = 0;
95884865Sobrien
95984865Sobrien  if (ic->comment)
96084865Sobrien    {
96184865Sobrien      if (!strncmp (ic->comment, "Format", 6))
96284865Sobrien        {
96384865Sobrien          /* assume that the first format seen is the most restrictive, and
96484865Sobrien             only keep a later one if it looks like it's more restrictive. */
96584865Sobrien          if (format)
96684865Sobrien            {
96784865Sobrien              if (strlen (ic->comment) < strlen (format))
96884865Sobrien                {
96984865Sobrien                  fprintf (stderr, "Warning: most recent format '%s'\n"
97084865Sobrien                           "appears more restrictive than '%s'\n",
97184865Sobrien                           ic->comment, format);
97284865Sobrien                  format = ic->comment;
97384865Sobrien                }
97484865Sobrien            }
97584865Sobrien          else
97684865Sobrien            format = ic->comment;
97784865Sobrien        }
97884865Sobrien      else if (!strncmp (ic->comment, "Field", 5))
97984865Sobrien        {
98084865Sobrien          if (field)
98184865Sobrien            fprintf (stderr, "Overlapping field %s->%s\n",
98284865Sobrien                     ic->comment, field);
98384865Sobrien          field = ic->comment;
98484865Sobrien        }
98584865Sobrien    }
98684865Sobrien
98784865Sobrien  /* an insn class matches anything that is the same followed by completers,
98884865Sobrien     except when the absence and presence of completers constitutes different
98984865Sobrien     instructions */
99084865Sobrien  if (ic->nsubs == 0 && ic->nxsubs == 0)
99184865Sobrien    {
99284865Sobrien      int is_mov = strncmp (idesc->name, "mov", 3) == 0;
99384865Sobrien      int plain_mov = strcmp (idesc->name, "mov") == 0;
99484865Sobrien      int len = strlen(ic->name);
99584865Sobrien
99684865Sobrien      resolved = ((strncmp (ic->name, idesc->name, len) == 0)
99784865Sobrien                  && (idesc->name[len] == '\0'
99884865Sobrien                      || idesc->name[len] == '.'));
99984865Sobrien
100084865Sobrien      /* all break and nop variations must match exactly */
100184865Sobrien      if (resolved &&
100284865Sobrien          (strcmp (ic->name, "break") == 0
100384865Sobrien           || strcmp (ic->name, "nop") == 0))
100484865Sobrien        resolved = strcmp (ic->name, idesc->name) == 0;
100584865Sobrien
100684865Sobrien      /* assume restrictions in the FORMAT/FIELD negate resolution,
100784865Sobrien         unless specifically allowed by clauses in this block */
100884865Sobrien      if (resolved && field)
100984865Sobrien        {
101084865Sobrien          /* check Field(sf)==sN against opcode sN */
101184865Sobrien          if (strstr(field, "(sf)==") != NULL)
101284865Sobrien            {
101384865Sobrien              char *sf;
101484865Sobrien              if ((sf = strstr (idesc->name, ".s")) != 0)
101584865Sobrien                {
101684865Sobrien                  resolved = strcmp (sf + 1, strstr (field, "==") + 2) == 0;
101784865Sobrien                }
101884865Sobrien            }
101984865Sobrien          /* check Field(lftype)==XXX */
102084865Sobrien          else if (strstr (field, "(lftype)") != NULL)
102184865Sobrien            {
102284865Sobrien              if (strstr (idesc->name, "fault") != NULL)
102384865Sobrien                resolved = strstr (field, "fault") != NULL;
102484865Sobrien              else
102584865Sobrien                resolved = strstr (field, "fault") == NULL;
102684865Sobrien            }
102784865Sobrien          /* handle Field(ctype)==XXX */
102884865Sobrien          else if (strstr (field, "(ctype)") != NULL)
102984865Sobrien            {
103084865Sobrien              if (strstr (idesc->name, "or.andcm"))
103184865Sobrien                resolved = strstr (field, "or.andcm") != NULL;
103284865Sobrien              else if (strstr (idesc->name, "and.orcm"))
103384865Sobrien                resolved = strstr (field, "and.orcm") != NULL;
103484865Sobrien              else if (strstr (idesc->name, "orcm"))
103584865Sobrien                resolved = strstr (field, "or orcm") != NULL;
103684865Sobrien              else if (strstr (idesc->name, "or"))
103784865Sobrien                resolved = strstr (field, "or orcm") != NULL;
103884865Sobrien              else if (strstr (idesc->name, "andcm"))
103984865Sobrien                resolved = strstr (field, "and andcm") != NULL;
104084865Sobrien              else if (strstr (idesc->name, "and"))
104184865Sobrien                resolved = strstr (field, "and andcm") != NULL;
104284865Sobrien              else if (strstr (idesc->name, "unc"))
104384865Sobrien                resolved = strstr (field, "unc") != NULL;
104484865Sobrien              else
104584865Sobrien                resolved = strcmp (field, "Field(ctype)==") == 0;
104684865Sobrien            }
104784865Sobrien        }
104884865Sobrien      if (resolved && format)
104984865Sobrien        {
105084865Sobrien          if (strncmp (idesc->name, "dep", 3) == 0
105184865Sobrien                   && strstr (format, "I13") != NULL)
105284865Sobrien            resolved = idesc->operands[1] == IA64_OPND_IMM8;
105384865Sobrien          else if (strncmp (idesc->name, "chk", 3) == 0
105484865Sobrien                   && strstr (format, "M21") != NULL)
105584865Sobrien            resolved = idesc->operands[0] == IA64_OPND_F2;
105684865Sobrien          else if (strncmp (idesc->name, "lfetch", 6) == 0)
105784865Sobrien            resolved = (strstr (format, "M14 M15") != NULL
105884865Sobrien                        && (idesc->operands[1] == IA64_OPND_R2
105984865Sobrien                            || idesc->operands[1] == IA64_OPND_IMM9b));
106084865Sobrien          else if (strncmp (idesc->name, "br.call", 7) == 0
106184865Sobrien                   && strstr (format, "B5") != NULL)
106284865Sobrien            resolved = idesc->operands[1] == IA64_OPND_B2;
106384865Sobrien          else if (strncmp (idesc->name, "br.call", 7) == 0
106484865Sobrien                   && strstr (format, "B3") != NULL)
106584865Sobrien            resolved = idesc->operands[1] == IA64_OPND_TGT25c;
106684865Sobrien          else if (strncmp (idesc->name, "brp", 3) == 0
106784865Sobrien                   && strstr (format, "B7") != NULL)
106884865Sobrien            resolved = idesc->operands[0] == IA64_OPND_B2;
106984865Sobrien          else if (strcmp (ic->name, "invala") == 0)
107084865Sobrien            resolved = strcmp (idesc->name, ic->name) == 0;
107184865Sobrien	  else if (strncmp (idesc->name, "st", 2) == 0
107284865Sobrien		   && strstr (format, "M5") != NULL)
107384865Sobrien	    resolved = idesc->flags & IA64_OPCODE_POSTINC;
107484865Sobrien          else
107584865Sobrien            resolved = 0;
107684865Sobrien        }
107784865Sobrien
107884865Sobrien      /* misc brl variations ('.cond' is optional);
107984865Sobrien         plain brl matches brl.cond */
108084865Sobrien      if (!resolved
108184865Sobrien          && (strcmp (idesc->name, "brl") == 0
108284865Sobrien              || strncmp (idesc->name, "brl.", 4) == 0)
108384865Sobrien          && strcmp (ic->name, "brl.cond") == 0)
108484865Sobrien        {
108584865Sobrien          resolved = 1;
108684865Sobrien        }
108784865Sobrien
108884865Sobrien      /* misc br variations ('.cond' is optional) */
108984865Sobrien      if (!resolved
109084865Sobrien          && (strcmp (idesc->name, "br") == 0
109184865Sobrien              || strncmp (idesc->name, "br.", 3) == 0)
109284865Sobrien          && strcmp (ic->name, "br.cond") == 0)
109384865Sobrien        {
109484865Sobrien          if (format)
109584865Sobrien            resolved = (strstr (format, "B4") != NULL
109684865Sobrien                        && idesc->operands[0] == IA64_OPND_B2)
109784865Sobrien              || (strstr (format, "B1") != NULL
109884865Sobrien                  && idesc->operands[0] == IA64_OPND_TGT25c);
109984865Sobrien          else
110084865Sobrien            resolved = 1;
110184865Sobrien        }
110284865Sobrien
110384865Sobrien      /* probe variations */
110484865Sobrien      if (!resolved && strncmp (idesc->name, "probe", 5) == 0)
110584865Sobrien        {
110684865Sobrien          resolved = strcmp (ic->name, "probe") == 0
110784865Sobrien            && !((strstr (idesc->name, "fault") != NULL)
110884865Sobrien                 ^ (format && strstr (format, "M40") != NULL));
110984865Sobrien        }
111084865Sobrien      /* mov variations */
111184865Sobrien      if (!resolved && is_mov)
111284865Sobrien        {
111384865Sobrien          if (plain_mov)
111484865Sobrien            {
111584865Sobrien              /* mov alias for fmerge */
111684865Sobrien              if (strcmp (ic->name, "fmerge") == 0)
111784865Sobrien                {
111884865Sobrien                  resolved = idesc->operands[0] == IA64_OPND_F1
111984865Sobrien                    && idesc->operands[1] == IA64_OPND_F3;
112084865Sobrien                }
112184865Sobrien              /* mov alias for adds (r3 or imm14) */
112284865Sobrien              else if (strcmp (ic->name, "adds") == 0)
112384865Sobrien                {
112484865Sobrien                  resolved = (idesc->operands[0] == IA64_OPND_R1
112584865Sobrien                              && (idesc->operands[1] == IA64_OPND_R3
112684865Sobrien                                  || (idesc->operands[1] == IA64_OPND_IMM14)));
112784865Sobrien                }
112884865Sobrien              /* mov alias for addl */
112984865Sobrien              else if (strcmp (ic->name, "addl") == 0)
113084865Sobrien                {
113184865Sobrien                  resolved = idesc->operands[0] == IA64_OPND_R1
113284865Sobrien                    && idesc->operands[1] == IA64_OPND_IMM22;
113384865Sobrien                }
113484865Sobrien            }
113584865Sobrien          /* some variants of mov and mov.[im] */
113684865Sobrien          if (!resolved && strncmp (ic->name, "mov_", 4) == 0)
113784865Sobrien            {
113884865Sobrien              resolved = in_iclass_mov_x (idesc, ic, format, field);
113984865Sobrien            }
114084865Sobrien        }
114184865Sobrien
114284865Sobrien      /* keep track of this so we can flag any insn classes which aren't
114384865Sobrien         mapped onto at least one real insn */
114484865Sobrien      if (resolved)
114584865Sobrien        {
114684865Sobrien          ic->terminal_resolved = 1;
114784865Sobrien        }
114884865Sobrien    }
114984865Sobrien  else for (i=0;i < ic->nsubs;i++)
115084865Sobrien    {
115184865Sobrien      if (in_iclass(idesc, ics[ic->subs[i]], format, field, notep))
115284865Sobrien        {
115384865Sobrien          int j;
115484865Sobrien          for (j=0;j < ic->nxsubs;j++)
115584865Sobrien            {
115684865Sobrien              if (in_iclass(idesc, ics[ic->xsubs[j]], NULL, NULL, NULL))
115784865Sobrien                return 0;
115884865Sobrien            }
115984865Sobrien          if (debug > 1)
116084865Sobrien            printf ("%s is in IC %s\n",
116184865Sobrien                    idesc->name, ic->name);
116284865Sobrien          resolved = 1;
116384865Sobrien          break;
116484865Sobrien        }
116584865Sobrien    }
116684865Sobrien
116784865Sobrien  /* If it's in this IC, add the IC note (if any) to the insn */
116884865Sobrien  if (resolved)
116984865Sobrien    {
117084865Sobrien      if (ic->note && notep)
117184865Sobrien        {
117284865Sobrien          if (*notep && *notep != ic->note)
117384865Sobrien            {
117484865Sobrien              fprintf (stderr, "Warning: overwriting note %d with note %d"
117584865Sobrien                       "(IC:%s)\n",
117684865Sobrien                       *notep, ic->note, ic->name);
117784865Sobrien            }
117884865Sobrien          *notep = ic->note;
117984865Sobrien        }
118084865Sobrien    }
118184865Sobrien
118284865Sobrien  return resolved;
118384865Sobrien}
118484865Sobrien
118584865Sobrien
118684865Sobrienstatic int
118784865Sobrienlookup_regindex (const char *name, int specifier)
118884865Sobrien{
118984865Sobrien  switch (specifier)
119084865Sobrien    {
119184865Sobrien    case IA64_RS_ARX:
119284865Sobrien      if (strstr (name, "[RSC]"))
119384865Sobrien        return 16;
119484865Sobrien      if (strstr (name, "[BSP]"))
119584865Sobrien        return 17;
119684865Sobrien      else if (strstr (name, "[BSPSTORE]"))
119784865Sobrien        return 18;
119884865Sobrien      else if (strstr (name, "[RNAT]"))
119984865Sobrien        return 19;
120084865Sobrien      else if (strstr (name, "[CCV]"))
120184865Sobrien        return 32;
120284865Sobrien      else if (strstr (name, "[ITC]"))
120384865Sobrien        return 44;
120484865Sobrien      else if (strstr (name, "[PFS]"))
120584865Sobrien        return 64;
120684865Sobrien      else if (strstr (name, "[LC]"))
120784865Sobrien        return 65;
120884865Sobrien      else if (strstr (name, "[EC]"))
120984865Sobrien        return 66;
121084865Sobrien      abort ();
121184865Sobrien    case IA64_RS_CRX:
121284865Sobrien      if (strstr (name, "[DCR]"))
121384865Sobrien        return 0;
121484865Sobrien      else if (strstr (name, "[ITM]"))
121584865Sobrien        return 1;
121684865Sobrien      else if (strstr (name, "[IVA]"))
121784865Sobrien        return 2;
121884865Sobrien      else if (strstr (name, "[PTA]"))
121984865Sobrien        return 8;
122084865Sobrien      else if (strstr (name, "[GPTA]"))
122184865Sobrien        return 9;
122284865Sobrien      else if (strstr (name, "[IPSR]"))
122384865Sobrien        return 16;
122484865Sobrien      else if (strstr (name, "[ISR]"))
122584865Sobrien        return 17;
122684865Sobrien      else if (strstr (name, "[IIP]"))
122784865Sobrien        return 19;
122884865Sobrien      else if (strstr (name, "[IFA]"))
122984865Sobrien        return 20;
123084865Sobrien      else if (strstr (name, "[ITIR]"))
123184865Sobrien        return 21;
123284865Sobrien      else if (strstr (name, "[IIPA]"))
123384865Sobrien        return 22;
123484865Sobrien      else if (strstr (name, "[IFS]"))
123584865Sobrien        return 23;
123684865Sobrien      else if (strstr (name, "[IIM]"))
123784865Sobrien        return 24;
123884865Sobrien      else if (strstr (name, "[IHA]"))
123984865Sobrien        return 25;
124084865Sobrien      else if (strstr (name, "[LID]"))
124184865Sobrien        return 64;
124284865Sobrien      else if (strstr (name, "[IVR]"))
124384865Sobrien        return 65;
124484865Sobrien      else if (strstr (name, "[TPR]"))
124584865Sobrien        return 66;
124684865Sobrien      else if (strstr (name, "[EOI]"))
124784865Sobrien        return 67;
124884865Sobrien      else if (strstr (name, "[ITV]"))
124984865Sobrien        return 72;
125084865Sobrien      else if (strstr (name, "[PMV]"))
125184865Sobrien        return 73;
125284865Sobrien      else if (strstr (name, "[CMCV]"))
125384865Sobrien        return 74;
125484865Sobrien      abort ();
125584865Sobrien    case IA64_RS_PSR:
125684865Sobrien      if (strstr (name, ".be"))
125784865Sobrien        return 1;
125884865Sobrien      else if (strstr (name, ".up"))
125984865Sobrien        return 2;
126084865Sobrien      else if (strstr (name, ".ac"))
126184865Sobrien        return 3;
126284865Sobrien      else if (strstr (name, ".mfl"))
126384865Sobrien        return 4;
126484865Sobrien      else if (strstr (name, ".mfh"))
126584865Sobrien        return 5;
126684865Sobrien      else if (strstr (name, ".ic"))
126784865Sobrien        return 13;
126884865Sobrien      else if (strstr (name, ".i"))
126984865Sobrien        return 14;
127084865Sobrien      else if (strstr (name, ".pk"))
127184865Sobrien        return 15;
127284865Sobrien      else if (strstr (name, ".dt"))
127384865Sobrien        return 17;
127484865Sobrien      else if (strstr (name, ".dfl"))
127584865Sobrien        return 18;
127684865Sobrien      else if (strstr (name, ".dfh"))
127784865Sobrien        return 19;
127884865Sobrien      else if (strstr (name, ".sp"))
127984865Sobrien        return 20;
128084865Sobrien      else if (strstr (name, ".pp"))
128184865Sobrien        return 21;
128284865Sobrien      else if (strstr (name, ".di"))
128384865Sobrien        return 22;
128484865Sobrien      else if (strstr (name, ".si"))
128584865Sobrien        return 23;
128684865Sobrien      else if (strstr (name, ".db"))
128784865Sobrien        return 24;
128884865Sobrien      else if (strstr (name, ".lp"))
128984865Sobrien        return 25;
129084865Sobrien      else if (strstr (name, ".tb"))
129184865Sobrien        return 26;
129284865Sobrien      else if (strstr (name, ".rt"))
129384865Sobrien        return 27;
129484865Sobrien      else if (strstr (name, ".cpl"))
129584865Sobrien        return 32;
129684865Sobrien      else if (strstr (name, ".rs"))
129784865Sobrien        return 34;
129884865Sobrien      else if (strstr (name, ".mc"))
129984865Sobrien        return 35;
130084865Sobrien      else if (strstr (name, ".it"))
130184865Sobrien        return 36;
130284865Sobrien      else if (strstr (name, ".id"))
130384865Sobrien        return 37;
130484865Sobrien      else if (strstr (name, ".da"))
130584865Sobrien        return 38;
130684865Sobrien      else if (strstr (name, ".dd"))
130784865Sobrien        return 39;
130884865Sobrien      else if (strstr (name, ".ss"))
130984865Sobrien        return 40;
131084865Sobrien      else if (strstr (name, ".ri"))
131184865Sobrien        return 41;
131284865Sobrien      else if (strstr (name, ".ed"))
131384865Sobrien        return 43;
131484865Sobrien      else if (strstr (name, ".bn"))
131584865Sobrien        return 44;
131684865Sobrien      else if (strstr (name, ".ia"))
131784865Sobrien        return 45;
131884865Sobrien      else
131984865Sobrien        abort ();
132084865Sobrien    default:
132184865Sobrien      break;
132284865Sobrien    }
132384865Sobrien  return REG_NONE;
132484865Sobrien}
132584865Sobrien
132684865Sobrienstatic int
132784865Sobrienlookup_specifier (const char *name)
132884865Sobrien{
132984865Sobrien  if (strchr (name, '%'))
133084865Sobrien    {
133184865Sobrien      if (strstr (name, "AR[K%]") != NULL)
133284865Sobrien        return IA64_RS_AR_K;
133384865Sobrien      if (strstr (name, "AR[UNAT]") != NULL)
133484865Sobrien        return IA64_RS_AR_UNAT;
133584865Sobrien      if (strstr (name, "AR%, % in 8") != NULL)
133684865Sobrien        return IA64_RS_AR;
133784865Sobrien      if (strstr (name, "AR%, % in 48") != NULL)
133884865Sobrien        return IA64_RS_ARb;
133984865Sobrien      if (strstr (name, "BR%") != NULL)
134084865Sobrien        return IA64_RS_BR;
134184865Sobrien      if (strstr (name, "CR[IRR%]") != NULL)
134284865Sobrien        return IA64_RS_CR_IRR;
134384865Sobrien      if (strstr (name, "CR[LRR%]") != NULL)
134484865Sobrien        return IA64_RS_CR_LRR;
134584865Sobrien      if (strstr (name, "CR%") != NULL)
134684865Sobrien        return IA64_RS_CR;
134784865Sobrien      if (strstr (name, "FR%, % in 0") != NULL)
134884865Sobrien        return IA64_RS_FR;
134984865Sobrien      if (strstr (name, "FR%, % in 2") != NULL)
135084865Sobrien        return IA64_RS_FRb;
135184865Sobrien      if (strstr (name, "GR%") != NULL)
135284865Sobrien        return IA64_RS_GR;
135384865Sobrien      if (strstr (name, "PR%, % in 1 ") != NULL)
135484865Sobrien        return IA64_RS_PR;
135584865Sobrien      if (strstr (name, "PR%, % in 16 ") != NULL)
135684865Sobrien	return IA64_RS_PRr;
135784865Sobrien
135884865Sobrien      fprintf (stderr, "Warning! Don't know how to specify %% dependency %s\n",
135984865Sobrien               name);
136084865Sobrien    }
136184865Sobrien  else if (strchr (name, '#'))
136284865Sobrien    {
136384865Sobrien      if (strstr (name, "CPUID#") != NULL)
136484865Sobrien        return IA64_RS_CPUID;
136584865Sobrien      if (strstr (name, "DBR#") != NULL)
136684865Sobrien        return IA64_RS_DBR;
136784865Sobrien      if (strstr (name, "IBR#") != NULL)
136884865Sobrien        return IA64_RS_IBR;
136984865Sobrien      if (strstr (name, "MSR#") != NULL)
137084865Sobrien	return IA64_RS_MSR;
137184865Sobrien      if (strstr (name, "PKR#") != NULL)
137284865Sobrien        return IA64_RS_PKR;
137384865Sobrien      if (strstr (name, "PMC#") != NULL)
137484865Sobrien        return IA64_RS_PMC;
137584865Sobrien      if (strstr (name, "PMD#") != NULL)
137684865Sobrien        return IA64_RS_PMD;
137784865Sobrien      if (strstr (name, "RR#") != NULL)
137884865Sobrien        return IA64_RS_RR;
137984865Sobrien
138084865Sobrien      fprintf (stderr, "Warning! Don't know how to specify # dependency %s\n",
138184865Sobrien               name);
138284865Sobrien    }
138384865Sobrien  else if (strncmp (name, "AR[FPSR]", 8) == 0)
138484865Sobrien    return IA64_RS_AR_FPSR;
138584865Sobrien  else if (strncmp (name, "AR[", 3) == 0)
138684865Sobrien    return IA64_RS_ARX;
138784865Sobrien  else if (strncmp (name, "CR[", 3) == 0)
138884865Sobrien    return IA64_RS_CRX;
138984865Sobrien  else if (strncmp (name, "PSR.", 4) == 0)
139084865Sobrien    return IA64_RS_PSR;
139184865Sobrien  else if (strcmp (name, "InService*") == 0)
139284865Sobrien    return IA64_RS_INSERVICE;
139384865Sobrien  else if (strcmp (name, "GR0") == 0)
139484865Sobrien    return IA64_RS_GR0;
139584865Sobrien  else if (strcmp (name, "CFM") == 0)
139684865Sobrien    return IA64_RS_CFM;
139784865Sobrien  else if (strcmp (name, "PR63") == 0)
139884865Sobrien    return IA64_RS_PR63;
139984865Sobrien  else if (strcmp (name, "RSE") == 0)
140084865Sobrien    return IA64_RS_RSE;
140184865Sobrien
140284865Sobrien  return IA64_RS_ANY;
140384865Sobrien}
140484865Sobrien
140584865Sobrienvoid
140684865Sobrienprint_dependency_table ()
140784865Sobrien{
140884865Sobrien  int i, j;
140984865Sobrien
141084865Sobrien  if (debug)
141184865Sobrien    {
141284865Sobrien      for (i=0;i < iclen;i++)
141384865Sobrien        {
141484865Sobrien          if (ics[i]->is_class)
141584865Sobrien            {
141684865Sobrien              if (!ics[i]->nsubs)
141784865Sobrien                {
141884865Sobrien                  fprintf (stderr, "Warning: IC:%s", ics[i]->name);
141984865Sobrien                  if (ics[i]->comment)
142084865Sobrien                    fprintf (stderr, "[%s]", ics[i]->comment);
142184865Sobrien                  fprintf (stderr, " has no terminals or sub-classes\n");
142284865Sobrien                }
142384865Sobrien            }
142484865Sobrien          else
142584865Sobrien            {
142684865Sobrien              if (!ics[i]->terminal_resolved && !ics[i]->orphan)
142784865Sobrien                {
142884865Sobrien                  fprintf(stderr, "Warning: no insns mapped directly to "
142984865Sobrien                          "terminal IC %s", ics[i]->name);
143084865Sobrien                  if (ics[i]->comment)
143184865Sobrien                    fprintf(stderr, "[%s] ", ics[i]->comment);
143284865Sobrien                  fprintf(stderr, "\n");
143384865Sobrien                }
143484865Sobrien            }
143584865Sobrien        }
143684865Sobrien
143784865Sobrien      for (i=0;i < iclen;i++)
143884865Sobrien        {
143984865Sobrien          if (ics[i]->orphan)
144084865Sobrien            {
144184865Sobrien              mark_used (ics[i], 1);
144284865Sobrien              fprintf (stderr, "Warning: class %s is defined but not used\n",
144384865Sobrien                       ics[i]->name);
144484865Sobrien            }
144584865Sobrien        }
144684865Sobrien
144784865Sobrien      if (debug > 1) for (i=0;i < rdepslen;i++)
144884865Sobrien        {
144984865Sobrien          static const char *mode_str[] = { "RAW", "WAW", "WAR" };
145084865Sobrien          if (rdeps[i]->total_chks == 0)
145184865Sobrien            {
145284865Sobrien              fprintf (stderr, "Warning: rsrc %s (%s) has no chks%s\n",
145384865Sobrien                       rdeps[i]->name, mode_str[rdeps[i]->mode],
145484865Sobrien                       rdeps[i]->total_regs ? "" : " or regs");
145584865Sobrien            }
145684865Sobrien          else if (rdeps[i]->total_regs == 0)
145784865Sobrien            {
145884865Sobrien              fprintf (stderr, "Warning: rsrc %s (%s) has no regs\n",
145984865Sobrien                       rdeps[i]->name, mode_str[rdeps[i]->mode]);
146084865Sobrien            }
146184865Sobrien        }
146284865Sobrien    }
146384865Sobrien
146484865Sobrien  /* the dependencies themselves */
146584865Sobrien  printf ("static const struct ia64_dependency\ndependencies[] = {\n");
146684865Sobrien  for (i=0;i < rdepslen;i++)
146784865Sobrien    {
146884865Sobrien      /* '%', '#', AR[], CR[], or PSR. indicates we need to specify the actual
146984865Sobrien         resource used */
147084865Sobrien      int specifier = lookup_specifier (rdeps[i]->name);
147184865Sobrien      int regindex = lookup_regindex (rdeps[i]->name, specifier);
147284865Sobrien
147384865Sobrien      printf ("  { \"%s\", %d, %d, %d, %d, ",
147484865Sobrien              rdeps[i]->name, specifier,
147584865Sobrien              (int)rdeps[i]->mode, (int)rdeps[i]->semantics, regindex);
147684865Sobrien      if (rdeps[i]->semantics == IA64_DVS_OTHER)
147784865Sobrien        printf ("\"%s\", ", rdeps[i]->extra);
147884865Sobrien      else
147984865Sobrien	printf ("NULL, ");
148084865Sobrien      printf("},\n");
148184865Sobrien    }
148284865Sobrien  printf ("};\n\n");
148384865Sobrien
148484865Sobrien  /* and dependency lists */
148584865Sobrien  for (i=0;i < dlistlen;i++)
148684865Sobrien    {
148784865Sobrien      int len = 2;
148884865Sobrien      printf ("static const short dep%d[] = {\n  ", i);
148984865Sobrien      for (j=0;j < dlists[i]->len; j++)
149084865Sobrien        {
149184865Sobrien          len += printf ("%d, ", dlists[i]->deps[j]);
149284865Sobrien          if (len > 75)
149384865Sobrien            {
149484865Sobrien              printf("\n  ");
149584865Sobrien              len = 2;
149684865Sobrien            }
149784865Sobrien        }
149884865Sobrien      printf ("\n};\n\n");
149984865Sobrien    }
150084865Sobrien
150184865Sobrien  /* and opcode dependency list */
150284865Sobrien  printf ("#define NELS(X) (sizeof(X)/sizeof(X[0]))\n");
150384865Sobrien  printf ("static const struct ia64_opcode_dependency\n");
150484865Sobrien  printf ("op_dependencies[] = {\n");
150584865Sobrien  for (i=0;i < opdeplen;i++)
150684865Sobrien    {
150784865Sobrien      printf ("  { ");
150884865Sobrien      if (opdeps[i]->chk == -1)
150984865Sobrien        printf ("0, NULL, ");
151084865Sobrien      else
151184865Sobrien        printf ("NELS(dep%d), dep%d, ", opdeps[i]->chk, opdeps[i]->chk);
151284865Sobrien      if (opdeps[i]->reg == -1)
151384865Sobrien        printf ("0, NULL, ");
151484865Sobrien      else
151584865Sobrien        printf ("NELS(dep%d), dep%d, ", opdeps[i]->reg, opdeps[i]->reg);
151684865Sobrien      printf ("},\n");
151784865Sobrien    }
151884865Sobrien  printf ("};\n\n");
151984865Sobrien}
152084865Sobrien
152184865Sobrien
152284865Sobrien/* Add STR to the string table. */
152384865Sobrien
152484865Sobrienstatic struct string_entry *
152584865Sobrieninsert_string (str)
152684865Sobrien     char *str;
152784865Sobrien{
152884865Sobrien  int start = 0, end = strtablen;
152984865Sobrien  int i, x;
153084865Sobrien
153184865Sobrien  if (strtablen == strtabtotlen)
153284865Sobrien    {
153384865Sobrien      strtabtotlen += 20;
153484865Sobrien      string_table = (struct string_entry **)
153584865Sobrien	xrealloc (string_table,
153684865Sobrien		  sizeof (struct string_entry **) * strtabtotlen);
153784865Sobrien    }
153884865Sobrien
153984865Sobrien  if (strtablen == 0)
154084865Sobrien    {
154184865Sobrien      strtablen = 1;
154284865Sobrien      string_table[0] = tmalloc (struct string_entry);
154384865Sobrien      string_table[0]->s = xstrdup (str);
154484865Sobrien      string_table[0]->num = 0;
154584865Sobrien      return string_table[0];
154684865Sobrien    }
154784865Sobrien
154884865Sobrien  if (strcmp (str, string_table[strtablen - 1]->s) > 0)
154984865Sobrien    {
155084865Sobrien      i = end;
155184865Sobrien    }
155284865Sobrien  else if (strcmp (str, string_table[0]->s) < 0)
155384865Sobrien    {
155484865Sobrien      i = 0;
155584865Sobrien    }
155684865Sobrien  else
155784865Sobrien    {
155884865Sobrien      while (1)
155984865Sobrien	{
156084865Sobrien	  int c;
156184865Sobrien
156284865Sobrien	  i = (start + end) / 2;
156384865Sobrien	  c = strcmp (str, string_table[i]->s);
156484865Sobrien	  if (c < 0)
156584865Sobrien	    {
156684865Sobrien	      end = i - 1;
156784865Sobrien	    }
156884865Sobrien	  else if (c == 0)
156984865Sobrien	    {
157084865Sobrien	      return string_table[i];
157184865Sobrien	    }
157284865Sobrien	  else
157384865Sobrien	    {
157484865Sobrien	      start = i + 1;
157584865Sobrien	    }
157684865Sobrien	  if (start > end)
157784865Sobrien	    {
157884865Sobrien	      break;
157984865Sobrien	    }
158084865Sobrien	}
158184865Sobrien    }
158284865Sobrien  for (; i > 0 && i < strtablen; i--)
158384865Sobrien    {
158484865Sobrien      if (strcmp (str, string_table[i - 1]->s) > 0)
158584865Sobrien	{
158684865Sobrien	  break;
158784865Sobrien	}
158884865Sobrien    }
158984865Sobrien  for (; i < strtablen; i++)
159084865Sobrien    {
159184865Sobrien      if (strcmp (str, string_table[i]->s) < 0)
159284865Sobrien	{
159384865Sobrien	  break;
159484865Sobrien	}
159584865Sobrien    }
159684865Sobrien  for (x = strtablen - 1; x >= i; x--)
159784865Sobrien    {
159884865Sobrien      string_table[x + 1] = string_table[x];
159984865Sobrien      string_table[x + 1]->num = x + 1;
160084865Sobrien    }
160184865Sobrien  string_table[i] = tmalloc (struct string_entry);
160284865Sobrien  string_table[i]->s = xstrdup (str);
160384865Sobrien  string_table[i]->num = i;
160484865Sobrien  strtablen++;
160584865Sobrien  return string_table[i];
160684865Sobrien}
160784865Sobrien
160884865Sobrienstruct bittree *
160984865Sobrienmake_bittree_entry ()
161084865Sobrien{
161184865Sobrien  struct bittree *res = tmalloc (struct bittree);
161284865Sobrien
161384865Sobrien  res->disent = NULL;
161484865Sobrien  res->bits[0] = NULL;
161584865Sobrien  res->bits[1] = NULL;
161684865Sobrien  res->bits[2] = NULL;
161784865Sobrien  res->skip_flag = 0;
161884865Sobrien  res->bits_to_skip = 0;
161984865Sobrien  return res;
162084865Sobrien}
162184865Sobrien
162284865Sobrienstruct disent *
162384865Sobrienadd_dis_table_ent (which, insn, order, completer_index)
162484865Sobrien     struct disent *which;
162584865Sobrien     int insn;
162684865Sobrien     int order;
162784865Sobrien     int completer_index;
162884865Sobrien{
162984865Sobrien  int ci = 0;
163084865Sobrien  struct disent *ent;
163184865Sobrien
163284865Sobrien  if (which != NULL)
163384865Sobrien    {
163484865Sobrien      ent = which;
163584865Sobrien
163684865Sobrien      ent->nextcnt++;
163784865Sobrien      while (ent->nexte != NULL)
163884865Sobrien	{
163984865Sobrien	  ent = ent->nexte;
164084865Sobrien	}
164184865Sobrien      ent = (ent->nexte = tmalloc (struct disent));
164284865Sobrien    }
164384865Sobrien  else
164484865Sobrien    {
164584865Sobrien      ent = tmalloc (struct disent);
164684865Sobrien      ent->next_ent = disinsntable;
164784865Sobrien      disinsntable = ent;
164884865Sobrien      which = ent;
164984865Sobrien    }
165084865Sobrien  ent->nextcnt = 0;
165184865Sobrien  ent->nexte = NULL;
165284865Sobrien  ent->insn = insn;
165384865Sobrien  ent->priority = order;
165484865Sobrien
165584865Sobrien  while (completer_index != 1)
165684865Sobrien    {
165784865Sobrien      ci = (ci << 1) | (completer_index & 1);
165884865Sobrien      completer_index >>= 1;
165984865Sobrien    }
166084865Sobrien  ent->completer_index = ci;
166184865Sobrien  return which;
166284865Sobrien}
166384865Sobrien
166484865Sobrienvoid
166584865Sobrienfinish_distable ()
166684865Sobrien{
166784865Sobrien  struct disent *ent = disinsntable;
166884865Sobrien  struct disent *prev = ent;
166984865Sobrien
167084865Sobrien  ent->ournum = 32768;
167184865Sobrien  while ((ent = ent->next_ent) != NULL)
167284865Sobrien    {
167384865Sobrien      ent->ournum = prev->ournum + prev->nextcnt + 1;
167484865Sobrien      prev = ent;
167584865Sobrien    }
167684865Sobrien}
167784865Sobrien
167884865Sobrienvoid
167984865Sobrieninsert_bit_table_ent (curr_ent, bit, opcode, mask,
168084865Sobrien                      opcodenum, order, completer_index)
168184865Sobrien     struct bittree *curr_ent;
168284865Sobrien     int bit;
168384865Sobrien     ia64_insn opcode;
168484865Sobrien     ia64_insn mask;
168584865Sobrien     int opcodenum;
168684865Sobrien     int order;
168784865Sobrien     int completer_index;
168884865Sobrien{
168984865Sobrien  ia64_insn m;
169084865Sobrien  int b;
169184865Sobrien  struct bittree *next;
169284865Sobrien
169384865Sobrien  if (bit == -1)
169484865Sobrien    {
169584865Sobrien      struct disent *nent = add_dis_table_ent (curr_ent->disent,
169684865Sobrien                                               opcodenum, order,
169784865Sobrien					       completer_index);
169884865Sobrien      curr_ent->disent = nent;
169984865Sobrien      return;
170084865Sobrien    }
170184865Sobrien
170284865Sobrien  m = ((ia64_insn) 1) << bit;
170384865Sobrien
170484865Sobrien  if (mask & m)
170584865Sobrien    {
170684865Sobrien      b = (opcode & m) ? 1 : 0;
170784865Sobrien    }
170884865Sobrien  else
170984865Sobrien    {
171084865Sobrien      b = 2;
171184865Sobrien    }
171284865Sobrien  next = curr_ent->bits[b];
171384865Sobrien  if (next == NULL)
171484865Sobrien    {
171584865Sobrien      next = make_bittree_entry ();
171684865Sobrien      curr_ent->bits[b] = next;
171784865Sobrien    }
171884865Sobrien  insert_bit_table_ent (next, bit - 1, opcode, mask, opcodenum, order,
171984865Sobrien			completer_index);
172084865Sobrien}
172184865Sobrien
172284865Sobrienvoid
172384865Sobrienadd_dis_entry (first, opcode, mask, opcodenum, ent, completer_index)
172484865Sobrien     struct bittree *first;
172584865Sobrien     ia64_insn opcode;
172684865Sobrien     ia64_insn mask;
172784865Sobrien     int opcodenum;
172884865Sobrien     struct completer_entry *ent;
172984865Sobrien     int completer_index;
173084865Sobrien{
173184865Sobrien  if (completer_index & (1 << 20))
173284865Sobrien    {
173384865Sobrien      abort ();
173484865Sobrien    }
173584865Sobrien
173684865Sobrien  while (ent != NULL)
173784865Sobrien    {
173884865Sobrien      ia64_insn newopcode = (opcode & (~ ent->mask)) | ent->bits;
173984865Sobrien      add_dis_entry (first, newopcode, mask, opcodenum, ent->addl_entries,
174084865Sobrien		     (completer_index << 1) | 1);
174184865Sobrien      if (ent->is_terminal)
174284865Sobrien	{
174384865Sobrien	  insert_bit_table_ent (bittree, 40, newopcode, mask,
174484865Sobrien                                opcodenum, opcode_count - ent->order - 1,
174584865Sobrien				(completer_index << 1) | 1);
174684865Sobrien	}
174784865Sobrien      completer_index <<= 1;
174884865Sobrien      ent = ent->alternative;
174984865Sobrien    }
175084865Sobrien}
175184865Sobrien
175284865Sobrien/* This optimization pass combines multiple "don't care" nodes. */
175384865Sobrienvoid
175484865Sobriencompact_distree (ent)
175584865Sobrien     struct bittree *ent;
175684865Sobrien{
175784865Sobrien#define IS_SKIP(ent) \
175884865Sobrien    ((ent->bits[2] !=NULL) \
175984865Sobrien     && (ent->bits[0] == NULL && ent->bits[1] == NULL && ent->skip_flag == 0))
176084865Sobrien
176184865Sobrien  int bitcnt = 0;
176284865Sobrien  struct bittree *nent = ent;
176384865Sobrien  int x;
176484865Sobrien
176584865Sobrien  while (IS_SKIP (nent))
176684865Sobrien    {
176784865Sobrien      bitcnt++;
176884865Sobrien      nent = nent->bits[2];
176984865Sobrien    }
177084865Sobrien
177184865Sobrien  if (bitcnt)
177284865Sobrien    {
177384865Sobrien      struct bittree *next = ent->bits[2];
177484865Sobrien
177584865Sobrien      ent->bits[0] = nent->bits[0];
177684865Sobrien      ent->bits[1] = nent->bits[1];
177784865Sobrien      ent->bits[2] = nent->bits[2];
177884865Sobrien      ent->disent = nent->disent;
177984865Sobrien      ent->skip_flag = 1;
178084865Sobrien      ent->bits_to_skip = bitcnt;
178184865Sobrien      while (next != nent)
178284865Sobrien	{
178384865Sobrien	  struct bittree *b = next;
178484865Sobrien	  next = next->bits[2];
178584865Sobrien	  free (b);
178684865Sobrien	}
178784865Sobrien      free (nent);
178884865Sobrien    }
178984865Sobrien
179084865Sobrien  for (x = 0; x < 3; x++)
179184865Sobrien    {
179284865Sobrien      struct bittree *i = ent->bits[x];
179384865Sobrien      if (i != NULL)
179484865Sobrien	{
179584865Sobrien	  compact_distree (i);
179684865Sobrien	}
179784865Sobrien    }
179884865Sobrien}
179984865Sobrien
180084865Sobrienstatic unsigned char *insn_list;
180184865Sobrienstatic int insn_list_len = 0;
180284865Sobrienstatic int tot_insn_list_len = 0;
180384865Sobrien
180484865Sobrien/* Generate the disassembler state machine corresponding to the tree
180584865Sobrien   in ENT.  */
180684865Sobrienvoid
180784865Sobriengen_dis_table (ent)
180884865Sobrien     struct bittree *ent;
180984865Sobrien{
181084865Sobrien  int x;
181184865Sobrien  int our_offset = insn_list_len;
181284865Sobrien  int bitsused = 5;
181384865Sobrien  int totbits = bitsused;
181484865Sobrien  int needed_bytes;
181584865Sobrien  int zero_count = 0;
181684865Sobrien  int zero_dest = 0;	/* initialize this with 0 to keep gcc quiet... */
181784865Sobrien
181884865Sobrien  /* If this is a terminal entry, there's no point in skipping any
181984865Sobrien     bits. */
182084865Sobrien  if (ent->skip_flag && ent->bits[0] == NULL && ent->bits[1] == NULL &&
182184865Sobrien      ent->bits[2] == NULL)
182284865Sobrien    {
182384865Sobrien      if (ent->disent == NULL)
182484865Sobrien	{
182584865Sobrien	  abort ();
182684865Sobrien	}
182784865Sobrien      else
182884865Sobrien	{
182984865Sobrien	  ent->skip_flag = 0;
183084865Sobrien	}
183184865Sobrien    }
183284865Sobrien
183384865Sobrien  /* Calculate the amount of space needed for this entry, or at least
183484865Sobrien     a conservatively large approximation. */
183584865Sobrien  if (ent->skip_flag)
183684865Sobrien    {
183784865Sobrien      totbits += 5;
183884865Sobrien    }
183984865Sobrien  for (x = 1; x < 3; x++)
184084865Sobrien    {
184184865Sobrien      if (ent->bits[x] != NULL)
184284865Sobrien	{
184384865Sobrien	  totbits += 16;
184484865Sobrien	}
184584865Sobrien    }
184684865Sobrien
184784865Sobrien  if (ent->disent != NULL)
184884865Sobrien    {
184984865Sobrien      if (ent->bits[2] != NULL)
185084865Sobrien	{
185184865Sobrien	  abort ();
185284865Sobrien	}
185384865Sobrien      totbits += 16;
185484865Sobrien    }
185584865Sobrien
185684865Sobrien  /* Now allocate the space. */
185784865Sobrien  needed_bytes = (totbits + 7) / 8;
185884865Sobrien  if ((needed_bytes + insn_list_len) > tot_insn_list_len)
185984865Sobrien    {
186084865Sobrien      tot_insn_list_len += 256;
186184865Sobrien      insn_list = (char *) xrealloc (insn_list, tot_insn_list_len);
186284865Sobrien    }
186384865Sobrien  our_offset = insn_list_len;
186484865Sobrien  insn_list_len += needed_bytes;
186584865Sobrien  memset (insn_list + our_offset, 0, needed_bytes);
186684865Sobrien
186784865Sobrien  /* Encode the skip entry by setting bit 6 set in the state op field,
186884865Sobrien     and store the # of bits to skip immediately after. */
186984865Sobrien  if (ent->skip_flag)
187084865Sobrien    {
187184865Sobrien      bitsused += 5;
187284865Sobrien      insn_list[our_offset + 0] |= 0x40 | ((ent->bits_to_skip >> 2) & 0xf);
187384865Sobrien      insn_list[our_offset + 1] |= ((ent->bits_to_skip & 3) << 6);
187484865Sobrien    }
187584865Sobrien
187684865Sobrien#define IS_ONLY_IFZERO(ENT) \
187784865Sobrien  ((ENT)->bits[0] != NULL && (ENT)->bits[1] == NULL && (ENT)->bits[2] == NULL \
187884865Sobrien   && (ENT)->disent == NULL && (ENT)->skip_flag == 0)
187984865Sobrien
188084865Sobrien  /* Store an "if (bit is zero)" instruction by setting bit 7 in the
188184865Sobrien     state op field. */
188284865Sobrien
188384865Sobrien  if (ent->bits[0] != NULL)
188484865Sobrien    {
188584865Sobrien      struct bittree *nent = ent->bits[0];
188684865Sobrien      zero_count = 0;
188784865Sobrien
188884865Sobrien      insn_list[our_offset] |= 0x80;
188984865Sobrien
189084865Sobrien      /* We can encode sequences of multiple "if (bit is zero)" tests
189184865Sobrien	 by storing the # of zero bits to check in the lower 3 bits of
189284865Sobrien	 the instruction.  However, this only applies if the state
189384865Sobrien	 solely tests for a zero bit.  */
189484865Sobrien
189584865Sobrien      if (IS_ONLY_IFZERO (ent))
189684865Sobrien	{
189784865Sobrien	  while (IS_ONLY_IFZERO (nent) && zero_count < 7)
189884865Sobrien	    {
189984865Sobrien	      nent = nent->bits[0];
190084865Sobrien	      zero_count++;
190184865Sobrien	    }
190284865Sobrien
190384865Sobrien	  insn_list[our_offset + 0] |= zero_count;
190484865Sobrien	}
190584865Sobrien      zero_dest = insn_list_len;
190684865Sobrien      gen_dis_table (nent);
190784865Sobrien    }
190884865Sobrien
190984865Sobrien  /* Now store the remaining tests.  We also handle a sole "termination
191084865Sobrien     entry" by storing it as an "any bit" test.  */
191184865Sobrien
191284865Sobrien  for (x = 1; x < 3; x++)
191384865Sobrien    {
191484865Sobrien      if (ent->bits[x] != NULL || (x == 2 && ent->disent != NULL))
191584865Sobrien	{
191684865Sobrien	  struct bittree *i = ent->bits[x];
191784865Sobrien	  int idest;
191884865Sobrien	  int currbits = 15;
191984865Sobrien
192084865Sobrien	  if (i != NULL)
192184865Sobrien	    {
192284865Sobrien	      /* If the instruction being branched to only consists of
192384865Sobrien		 a termination entry, use the termination entry as the
192484865Sobrien		 place to branch to instead.  */
192584865Sobrien	      if (i->bits[0] == NULL && i->bits[1] == NULL
192684865Sobrien		  && i->bits[2] == NULL && i->disent != NULL)
192784865Sobrien		{
192884865Sobrien		  idest = i->disent->ournum;
192984865Sobrien		  i = NULL;
193084865Sobrien		}
193184865Sobrien	      else
193284865Sobrien		{
193384865Sobrien		  idest = insn_list_len - our_offset;
193484865Sobrien		}
193584865Sobrien	    }
193684865Sobrien	  else
193784865Sobrien	    {
193884865Sobrien	      idest = ent->disent->ournum;
193984865Sobrien	    }
194084865Sobrien
194184865Sobrien	  /* If the destination offset for the if (bit is 1) test is less
194284865Sobrien	     than 256 bytes away, we can store it as 8-bits instead of 16;
194384865Sobrien	     the instruction has bit 5 set for the 16-bit address, and bit
194484865Sobrien	     4 for the 8-bit address.  Since we've already allocated 16
194584865Sobrien	     bits for the address we need to deallocate the space.
194684865Sobrien
194784865Sobrien	     Note that branchings within the table are relative, and
194884865Sobrien	     there are no branches that branch past our instruction yet
194984865Sobrien	     so we do not need to adjust any other offsets. */
195084865Sobrien
195184865Sobrien	  if (x == 1)
195284865Sobrien	    {
195384865Sobrien	      if (idest <= 256)
195484865Sobrien		{
195584865Sobrien		  int start = our_offset + bitsused / 8 + 1;
195684865Sobrien
195784865Sobrien		  memmove (insn_list + start,
195884865Sobrien			   insn_list + start + 1,
195984865Sobrien			   insn_list_len - (start + 1));
196084865Sobrien		  currbits = 7;
196184865Sobrien		  totbits -= 8;
196284865Sobrien		  needed_bytes--;
196384865Sobrien		  insn_list_len--;
196484865Sobrien		  insn_list[our_offset] |= 0x10;
196584865Sobrien		  idest--;
196684865Sobrien		}
196784865Sobrien	      else
196884865Sobrien		{
196984865Sobrien		  insn_list[our_offset] |= 0x20;
197084865Sobrien		}
197184865Sobrien	    }
197284865Sobrien	  else
197384865Sobrien	    {
197484865Sobrien	      /* An instruction which solely consists of a termination
197584865Sobrien		 marker and whose disassembly name index is < 4096
197684865Sobrien		 can be stored in 16 bits.  The encoding is slightly
197784865Sobrien		 odd; the upper 4 bits of the instruction are 0x3, and
197884865Sobrien		 bit 3 loses its normal meaning.  */
197984865Sobrien
198084865Sobrien	      if (ent->bits[0] == NULL && ent->bits[1] == NULL
198184865Sobrien		  && ent->bits[2] == NULL && ent->skip_flag == 0
198284865Sobrien		  && ent->disent != NULL
198384865Sobrien		  && ent->disent->ournum < (32768 + 4096))
198484865Sobrien		{
198584865Sobrien		  int start = our_offset + bitsused / 8 + 1;
198684865Sobrien
198784865Sobrien		  memmove (insn_list + start,
198884865Sobrien			   insn_list + start + 1,
198984865Sobrien			   insn_list_len - (start + 1));
199084865Sobrien		  currbits = 11;
199184865Sobrien		  totbits -= 5;
199284865Sobrien		  bitsused--;
199384865Sobrien		  needed_bytes--;
199484865Sobrien		  insn_list_len--;
199584865Sobrien		  insn_list[our_offset] |= 0x30;
199684865Sobrien		  idest &= ~32768;
199784865Sobrien		}
199884865Sobrien	      else
199984865Sobrien		{
200084865Sobrien		  insn_list[our_offset] |= 0x08;
200184865Sobrien		}
200284865Sobrien	    }
200384865Sobrien	  if (debug)
200484865Sobrien	    {
200584865Sobrien	      int id = idest;
200684865Sobrien
200784865Sobrien	      if (i == NULL)
200884865Sobrien		{
200984865Sobrien		  id |= 32768;
201084865Sobrien		}
201184865Sobrien	      else if (! (id & 32768))
201284865Sobrien		{
201384865Sobrien		  id += our_offset;
201484865Sobrien		}
201584865Sobrien	      if (x == 1)
201684865Sobrien		{
201784865Sobrien		  printf ("%d: if (1) goto %d\n", our_offset, id);
201884865Sobrien		}
201984865Sobrien	      else
202084865Sobrien		{
202184865Sobrien		  printf ("%d: try %d\n", our_offset, id);
202284865Sobrien		}
202384865Sobrien	    }
202484865Sobrien
202584865Sobrien	  /* Store the address of the entry being branched to. */
202684865Sobrien	  while (currbits >= 0)
202784865Sobrien	    {
202884865Sobrien	      char *byte = insn_list + our_offset + bitsused / 8;
202984865Sobrien
203084865Sobrien	      if (idest & (1 << currbits))
203184865Sobrien		{
203284865Sobrien		  *byte |= (1 << (7 - (bitsused % 8)));
203384865Sobrien		}
203484865Sobrien	      bitsused++;
203584865Sobrien	      currbits--;
203684865Sobrien	    }
203784865Sobrien
203884865Sobrien	  /* Now generate the states for the entry being branched to. */
203984865Sobrien	  if (i != NULL)
204084865Sobrien	    {
204184865Sobrien	      gen_dis_table (i);
204284865Sobrien	    }
204384865Sobrien
204484865Sobrien	}
204584865Sobrien    }
204684865Sobrien  if (debug)
204784865Sobrien    {
204884865Sobrien      if (ent->skip_flag)
204984865Sobrien	{
205084865Sobrien	  printf ("%d: skipping %d\n", our_offset, ent->bits_to_skip);
205184865Sobrien	}
205284865Sobrien
205384865Sobrien      if (ent->bits[0] != NULL)
205484865Sobrien	{
205584865Sobrien	  printf ("%d: if (0:%d) goto %d\n", our_offset, zero_count + 1,
205684865Sobrien		  zero_dest);
205784865Sobrien	}
205884865Sobrien    }
205984865Sobrien  if (bitsused != totbits)
206084865Sobrien    {
206184865Sobrien      abort ();
206284865Sobrien    }
206384865Sobrien}
206484865Sobrien
206584865Sobrienvoid
206684865Sobrienprint_dis_table ()
206784865Sobrien{
206884865Sobrien  int x;
206984865Sobrien  struct disent *cent = disinsntable;
207084865Sobrien
207184865Sobrien  printf ("static const char dis_table[] = {\n");
207284865Sobrien  for (x = 0; x < insn_list_len; x++)
207384865Sobrien    {
207484865Sobrien      if ((x > 0) && ((x % 12) == 0))
207584865Sobrien	{
207684865Sobrien	  printf ("\n");
207784865Sobrien	}
207884865Sobrien      printf ("0x%02x, ", insn_list[x]);
207984865Sobrien    }
208084865Sobrien  printf ("\n};\n\n");
208184865Sobrien
208284865Sobrien  printf ("static const struct ia64_dis_names ia64_dis_names[] = {\n");
208384865Sobrien  while (cent != NULL)
208484865Sobrien    {
208584865Sobrien      struct disent *ent = cent;
208684865Sobrien
208784865Sobrien      while (ent != NULL)
208884865Sobrien	{
208984865Sobrien	  printf ("{ 0x%x, %d, %d, %d },\n", ent->completer_index,
209084865Sobrien		  ent->insn, (ent->nexte != NULL ? 1 : 0),
209184865Sobrien                  ent->priority);
209284865Sobrien	  ent = ent->nexte;
209384865Sobrien	}
209484865Sobrien      cent = cent->next_ent;
209584865Sobrien    }
209684865Sobrien  printf ("};\n\n");
209784865Sobrien}
209884865Sobrien
209984865Sobrienvoid
210084865Sobriengenerate_disassembler ()
210184865Sobrien{
210284865Sobrien  int i;
210384865Sobrien
210484865Sobrien  bittree = make_bittree_entry ();
210584865Sobrien
210684865Sobrien  for (i=0; i < otlen;i++)
210784865Sobrien    {
210884865Sobrien      struct main_entry *ptr = ordered_table[i];
210984865Sobrien
211084865Sobrien      if (ptr->opcode->type != IA64_TYPE_DYN)
211184865Sobrien	{
211284865Sobrien	  add_dis_entry (bittree,
211384865Sobrien			 ptr->opcode->opcode, ptr->opcode->mask,
211484865Sobrien                         ptr->main_index,
211584865Sobrien			 ptr->completers, 1);
211684865Sobrien	}
211784865Sobrien    }
211884865Sobrien
211984865Sobrien  compact_distree (bittree);
212084865Sobrien  finish_distable ();
212184865Sobrien  gen_dis_table (bittree);
212284865Sobrien
212384865Sobrien  print_dis_table ();
212484865Sobrien}
212584865Sobrien
212684865Sobrienvoid
212784865Sobrienprint_string_table ()
212884865Sobrien{
212984865Sobrien  int x;
213084865Sobrien  char lbuf[80], buf[80];
213184865Sobrien  int blen = 0;
213284865Sobrien
213384865Sobrien  printf ("static const char *ia64_strings[] = {\n");
213484865Sobrien  lbuf[0] = '\0';
213584865Sobrien  for (x = 0; x < strtablen; x++)
213684865Sobrien    {
213784865Sobrien      int len;
213884865Sobrien
213984865Sobrien      if (strlen (string_table[x]->s) > 75)
214084865Sobrien	{
214184865Sobrien	  abort ();
214284865Sobrien	}
214384865Sobrien      sprintf (buf, " \"%s\",", string_table[x]->s);
214484865Sobrien      len = strlen (buf);
214584865Sobrien      if ((blen + len) > 75)
214684865Sobrien	{
214784865Sobrien	  printf (" %s\n", lbuf);
214884865Sobrien	  lbuf[0] = '\0';
214984865Sobrien	  blen = 0;
215084865Sobrien	}
215184865Sobrien      strcat (lbuf, buf);
215284865Sobrien      blen += len;
215384865Sobrien    }
215484865Sobrien  if (blen > 0)
215584865Sobrien    {
215684865Sobrien      printf (" %s\n", lbuf);
215784865Sobrien    }
215884865Sobrien  printf ("};\n\n");
215984865Sobrien}
216084865Sobrien
216184865Sobrienstatic struct completer_entry **glist;
216284865Sobrienstatic int glistlen = 0;
216384865Sobrienstatic int glisttotlen = 0;
216484865Sobrien
216584865Sobrien/* If the completer trees ENT1 and ENT2 are equal, return 1. */
216684865Sobrien
216784865Sobrienint
216884865Sobriencompleter_entries_eq (ent1, ent2)
216984865Sobrien     struct completer_entry *ent1, *ent2;
217084865Sobrien{
217184865Sobrien  while (ent1 != NULL && ent2 != NULL)
217284865Sobrien    {
217384865Sobrien      if (ent1->name->num != ent2->name->num
217484865Sobrien	  || ent1->bits != ent2->bits
217584865Sobrien	  || ent1->mask != ent2->mask
217684865Sobrien	  || ent1->is_terminal != ent2->is_terminal
217784865Sobrien          || ent1->dependencies != ent2->dependencies
217884865Sobrien          || ent1->order != ent2->order)
217984865Sobrien	{
218084865Sobrien	  return 0;
218184865Sobrien	}
218284865Sobrien      if (! completer_entries_eq (ent1->addl_entries, ent2->addl_entries))
218384865Sobrien	{
218484865Sobrien	  return 0;
218584865Sobrien	}
218684865Sobrien      ent1 = ent1->alternative;
218784865Sobrien      ent2 = ent2->alternative;
218884865Sobrien    }
218984865Sobrien  return ent1 == ent2;
219084865Sobrien}
219184865Sobrien
219284865Sobrien/* Insert ENT into the global list of completers and return it.  If an
219384865Sobrien   equivalent entry (according to completer_entries_eq) already exists,
219484865Sobrien   it is returned instead. */
219584865Sobrienstruct completer_entry *
219684865Sobrieninsert_gclist (ent)
219784865Sobrien     struct completer_entry *ent;
219884865Sobrien{
219984865Sobrien  if (ent != NULL)
220084865Sobrien    {
220184865Sobrien      int i;
220284865Sobrien      int x;
220384865Sobrien      int start = 0, end;
220484865Sobrien
220584865Sobrien      ent->addl_entries = insert_gclist (ent->addl_entries);
220684865Sobrien      ent->alternative = insert_gclist (ent->alternative);
220784865Sobrien
220884865Sobrien      i = glistlen / 2;
220984865Sobrien      end = glistlen;
221084865Sobrien
221184865Sobrien      if (glisttotlen == glistlen)
221284865Sobrien	{
221384865Sobrien	  glisttotlen += 20;
221484865Sobrien	  glist = (struct completer_entry **)
221584865Sobrien	    xrealloc (glist, sizeof (struct completer_entry *) * glisttotlen);
221684865Sobrien	}
221784865Sobrien
221884865Sobrien      if (glistlen == 0)
221984865Sobrien	{
222084865Sobrien	  glist[0] = ent;
222184865Sobrien	  glistlen = 1;
222284865Sobrien	  return ent;
222384865Sobrien	}
222484865Sobrien
222584865Sobrien      if (ent->name->num < glist[0]->name->num)
222684865Sobrien	{
222784865Sobrien	  i = 0;
222884865Sobrien	}
222984865Sobrien      else if (ent->name->num > glist[end - 1]->name->num)
223084865Sobrien	{
223184865Sobrien	  i = end;
223284865Sobrien	}
223384865Sobrien      else
223484865Sobrien	{
223584865Sobrien	  int c;
223684865Sobrien
223784865Sobrien	  while (1)
223884865Sobrien	    {
223984865Sobrien	      i = (start + end) / 2;
224084865Sobrien	      c = ent->name->num - glist[i]->name->num;
224184865Sobrien	      if (c < 0)
224284865Sobrien		{
224384865Sobrien		  end = i - 1;
224484865Sobrien		}
224584865Sobrien	      else if (c == 0)
224684865Sobrien		{
224784865Sobrien		  while (i > 0
224884865Sobrien			 && ent->name->num == glist[i - 1]->name->num)
224984865Sobrien		    {
225084865Sobrien		      i--;
225184865Sobrien		    }
225284865Sobrien		  break;
225384865Sobrien		}
225484865Sobrien	      else
225584865Sobrien		{
225684865Sobrien		  start = i + 1;
225784865Sobrien		}
225884865Sobrien	      if (start > end)
225984865Sobrien		{
226084865Sobrien		  break;
226184865Sobrien		}
226284865Sobrien	    }
226384865Sobrien	  if (c == 0)
226484865Sobrien	    {
226584865Sobrien	      while (i < glistlen)
226684865Sobrien		{
226784865Sobrien		  if (ent->name->num != glist[i]->name->num)
226884865Sobrien		    {
226984865Sobrien		      break;
227084865Sobrien		    }
227184865Sobrien		  if (completer_entries_eq (ent, glist[i]))
227284865Sobrien		    {
227384865Sobrien		      return glist[i];
227484865Sobrien		    }
227584865Sobrien		  i++;
227684865Sobrien		}
227784865Sobrien	    }
227884865Sobrien	}
227984865Sobrien      for (; i > 0 && i < glistlen; i--)
228084865Sobrien	{
228184865Sobrien	  if (ent->name->num >= glist[i - 1]->name->num)
228284865Sobrien	    {
228384865Sobrien	      break;
228484865Sobrien	    }
228584865Sobrien	}
228684865Sobrien      for (; i < glistlen; i++)
228784865Sobrien	{
228884865Sobrien	  if (ent->name->num < glist[i]->name->num)
228984865Sobrien	    {
229084865Sobrien	      break;
229184865Sobrien	    }
229284865Sobrien	}
229384865Sobrien      for (x = glistlen - 1; x >= i; x--)
229484865Sobrien	{
229584865Sobrien	  glist[x + 1] = glist[x];
229684865Sobrien	}
229784865Sobrien      glist[i] = ent;
229884865Sobrien      glistlen++;
229984865Sobrien    }
230084865Sobrien  return ent;
230184865Sobrien}
230284865Sobrien
230384865Sobrienstatic int
230484865Sobrienget_prefix_len (name)
230584865Sobrien     const char *name;
230684865Sobrien{
230784865Sobrien  char *c;
230884865Sobrien
230984865Sobrien  if (name[0] == '\0')
231084865Sobrien    {
231184865Sobrien      return 0;
231284865Sobrien    }
231384865Sobrien
231484865Sobrien  c = strchr (name, '.');
231584865Sobrien  if (c != NULL)
231684865Sobrien    {
231784865Sobrien      return c - name;
231884865Sobrien    }
231984865Sobrien  else
232084865Sobrien    {
232184865Sobrien      return strlen (name);
232284865Sobrien    }
232384865Sobrien}
232484865Sobrien
232584865Sobrienstatic void
232684865Sobriencompute_completer_bits (ment, ent)
232784865Sobrien     struct main_entry *ment;
232884865Sobrien     struct completer_entry *ent;
232984865Sobrien{
233084865Sobrien  while (ent != NULL)
233184865Sobrien    {
233284865Sobrien      compute_completer_bits (ment, ent->addl_entries);
233384865Sobrien
233484865Sobrien      if (ent->is_terminal)
233584865Sobrien	{
233684865Sobrien	  ia64_insn mask = 0;
233784865Sobrien	  ia64_insn our_bits = ent->bits;
233884865Sobrien	  struct completer_entry *p = ent->parent;
233984865Sobrien	  ia64_insn p_bits;
234084865Sobrien	  int x;
234184865Sobrien
234284865Sobrien	  while (p != NULL && ! p->is_terminal)
234384865Sobrien	    {
234484865Sobrien	      p = p->parent;
234584865Sobrien	    }
234684865Sobrien
234784865Sobrien	  if (p != NULL)
234884865Sobrien	    {
234984865Sobrien	      p_bits = p->bits;
235084865Sobrien	    }
235184865Sobrien	  else
235284865Sobrien	    {
235384865Sobrien	      p_bits = ment->opcode->opcode;
235484865Sobrien	    }
235584865Sobrien
235684865Sobrien	  for (x = 0; x < 64; x++)
235784865Sobrien	    {
235884865Sobrien	      ia64_insn m = ((ia64_insn) 1) << x;
235984865Sobrien	      if ((p_bits & m) != (our_bits & m))
236084865Sobrien		{
236184865Sobrien		  mask |= m;
236284865Sobrien		}
236384865Sobrien	      else
236484865Sobrien		{
236584865Sobrien		  our_bits &= ~m;
236684865Sobrien		}
236784865Sobrien	    }
236884865Sobrien	  ent->bits = our_bits;
236984865Sobrien	  ent->mask = mask;
237084865Sobrien	}
237184865Sobrien      else
237284865Sobrien	{
237384865Sobrien	  ent->bits = 0;
237484865Sobrien	  ent->mask = 0;
237584865Sobrien	}
237684865Sobrien
237784865Sobrien      ent = ent->alternative;
237884865Sobrien    }
237984865Sobrien}
238084865Sobrien
238184865Sobrien/* Find identical completer trees that are used in different
238284865Sobrien   instructions and collapse their entries. */
238384865Sobrienvoid
238484865Sobriencollapse_redundant_completers ()
238584865Sobrien{
238684865Sobrien  struct main_entry *ptr;
238784865Sobrien  int x;
238884865Sobrien
238984865Sobrien  for (ptr = maintable; ptr != NULL; ptr = ptr->next)
239084865Sobrien    {
239184865Sobrien      if (ptr->completers == NULL)
239284865Sobrien	{
239384865Sobrien	  abort ();
239484865Sobrien	}
239584865Sobrien      compute_completer_bits (ptr, ptr->completers);
239684865Sobrien      ptr->completers = insert_gclist (ptr->completers);
239784865Sobrien    }
239884865Sobrien
239984865Sobrien  /* The table has been finalized, now number the indexes.  */
240084865Sobrien  for (x = 0; x < glistlen; x++)
240184865Sobrien    {
240284865Sobrien      glist[x]->num = x;
240384865Sobrien    }
240484865Sobrien}
240584865Sobrien
240684865Sobrien
240784865Sobrien/* attach two lists of dependencies to each opcode.
240884865Sobrien   1) all resources which, when already marked in use, conflict with this
240984865Sobrien   opcode (chks)
241084865Sobrien   2) all resources which must be marked in use when this opcode is used
241184865Sobrien   (regs)
241284865Sobrien*/
241384865Sobrienint
241484865Sobrieninsert_opcode_dependencies (opc, cmp)
241584865Sobrien     struct ia64_opcode *opc;
241684865Sobrien     struct completer_entry *cmp ATTRIBUTE_UNUSED;
241784865Sobrien{
241884865Sobrien  /* note all resources which point to this opcode.  rfi has the most chks
241984865Sobrien     (79) and cmpxchng has the most regs (54) so 100 here should be enough */
242084865Sobrien  int i;
242184865Sobrien  int nregs = 0;
242284865Sobrien  unsigned short regs[256];
242384865Sobrien  int nchks = 0;
242484865Sobrien  unsigned short chks[256];
242584865Sobrien  /* flag insns for which no class matched; there should be none */
242684865Sobrien  int no_class_found = 1;
242784865Sobrien
242884865Sobrien  for (i=0;i < rdepslen;i++)
242984865Sobrien    {
243084865Sobrien      struct rdep *rs = rdeps[i];
243184865Sobrien      int j;
243284865Sobrien
243384865Sobrien      if (strcmp (opc->name, "cmp.eq.and") == 0
243484865Sobrien          && strncmp (rs->name, "PR%", 3) == 0
243584865Sobrien          && rs->mode == 1)
243684865Sobrien        no_class_found = 99;
243784865Sobrien
243884865Sobrien      for (j=0; j < rs->nregs;j++)
243984865Sobrien        {
244084865Sobrien          int ic_note = 0;
244184865Sobrien
244284865Sobrien          if (in_iclass (opc, ics[rs->regs[j]], NULL, NULL, &ic_note))
244384865Sobrien            {
244484865Sobrien              /* We can ignore ic_note 11 for non PR resources */
244584865Sobrien              if (ic_note == 11 && strncmp (rs->name, "PR", 2) != 0)
244684865Sobrien                ic_note = 0;
244784865Sobrien
244884865Sobrien              if (ic_note != 0 && rs->regnotes[j] != 0
244984865Sobrien                  && ic_note != rs->regnotes[j]
245084865Sobrien                  && !(ic_note == 11 && rs->regnotes[j] == 1))
245184865Sobrien                fprintf (stderr, "Warning: IC note %d in opcode %s (IC:%s)"
245284865Sobrien                         " conflicts with resource %s note %d\n",
245384865Sobrien                         ic_note, opc->name, ics[rs->regs[j]]->name,
245484865Sobrien                         rs->name, rs->regnotes[j]);
245584865Sobrien              /* Instruction class notes override resource notes.
245684865Sobrien                 So far, only note 11 applies to an IC instead of a resource,
245784865Sobrien                 and note 11 implies note 1.
245884865Sobrien               */
245984865Sobrien              if (ic_note)
246084865Sobrien                regs[nregs++] = RDEP(ic_note, i);
246184865Sobrien              else
246284865Sobrien                regs[nregs++] = RDEP(rs->regnotes[j], i);
246384865Sobrien              no_class_found = 0;
246484865Sobrien              ++rs->total_regs;
246584865Sobrien            }
246684865Sobrien        }
246784865Sobrien      for (j=0;j < rs->nchks;j++)
246884865Sobrien        {
246984865Sobrien          int ic_note = 0;
247084865Sobrien
247184865Sobrien          if (in_iclass (opc, ics[rs->chks[j]], NULL, NULL, &ic_note))
247284865Sobrien            {
247384865Sobrien              /* We can ignore ic_note 11 for non PR resources */
247484865Sobrien              if (ic_note == 11 && strncmp (rs->name, "PR", 2) != 0)
247584865Sobrien                ic_note = 0;
247684865Sobrien
247784865Sobrien              if (ic_note != 0 && rs->chknotes[j] != 0
247884865Sobrien                  && ic_note != rs->chknotes[j]
247984865Sobrien                  && !(ic_note == 11 && rs->chknotes[j] == 1))
248084865Sobrien                fprintf (stderr, "Warning: IC note %d for opcode %s (IC:%s)"
248184865Sobrien                         " conflicts with resource %s note %d\n",
248284865Sobrien                         ic_note, opc->name, ics[rs->chks[j]]->name,
248384865Sobrien                         rs->name, rs->chknotes[j]);
248484865Sobrien              if (ic_note)
248584865Sobrien                chks[nchks++] = RDEP(ic_note, i);
248684865Sobrien              else
248784865Sobrien                chks[nchks++] = RDEP(rs->chknotes[j], i);
248884865Sobrien              no_class_found = 0;
248984865Sobrien              ++rs->total_chks;
249084865Sobrien            }
249184865Sobrien        }
249284865Sobrien    }
249384865Sobrien
249484865Sobrien  if (no_class_found)
249584865Sobrien    fprintf (stderr, "Warning: opcode %s has no class (ops %d %d %d)\n",
249684865Sobrien             opc->name,
249784865Sobrien             opc->operands[0], opc->operands[1], opc->operands[2]);
249884865Sobrien
249984865Sobrien  return insert_dependencies (nchks, chks, nregs, regs);
250084865Sobrien}
250184865Sobrien
250284865Sobrienvoid
250384865Sobrieninsert_completer_entry (opc, tabent, order)
250484865Sobrien     struct ia64_opcode *opc;
250584865Sobrien     struct main_entry *tabent;
250684865Sobrien     int order;
250784865Sobrien{
250884865Sobrien  struct completer_entry **ptr = &tabent->completers;
250984865Sobrien  struct completer_entry *parent = NULL;
251084865Sobrien  char pcopy[129], *prefix;
251184865Sobrien  int at_end = 0;
251284865Sobrien
251384865Sobrien  if (strlen (opc->name) > 128)
251484865Sobrien    {
251584865Sobrien      abort ();
251684865Sobrien    }
251784865Sobrien  strcpy (pcopy, opc->name);
251884865Sobrien  prefix = pcopy + get_prefix_len (pcopy);
251984865Sobrien  if (prefix[0] != '\0')
252084865Sobrien    {
252184865Sobrien      prefix++;
252284865Sobrien    }
252384865Sobrien
252484865Sobrien  while (! at_end)
252584865Sobrien    {
252684865Sobrien      int need_new_ent = 1;
252784865Sobrien      int plen = get_prefix_len (prefix);
252884865Sobrien      struct string_entry *sent;
252984865Sobrien
253084865Sobrien      at_end = (prefix[plen] == '\0');
253184865Sobrien      prefix[plen] = '\0';
253284865Sobrien      sent = insert_string (prefix);
253384865Sobrien
253484865Sobrien      while (*ptr != NULL)
253584865Sobrien	{
253684865Sobrien	  int cmpres = sent->num - (*ptr)->name->num;
253784865Sobrien
253884865Sobrien	  if (cmpres == 0)
253984865Sobrien	    {
254084865Sobrien	      need_new_ent = 0;
254184865Sobrien	      break;
254284865Sobrien	    }
254384865Sobrien	  else
254484865Sobrien	    {
254584865Sobrien	      ptr = &((*ptr)->alternative);
254684865Sobrien	    }
254784865Sobrien	}
254884865Sobrien      if (need_new_ent)
254984865Sobrien	{
255084865Sobrien	  struct completer_entry *nent = tmalloc (struct completer_entry);
255184865Sobrien	  nent->name = sent;
255284865Sobrien	  nent->parent = parent;
255384865Sobrien	  nent->addl_entries = NULL;
255484865Sobrien	  nent->alternative = *ptr;
255584865Sobrien	  *ptr = nent;
255684865Sobrien	  nent->is_terminal = 0;
255784865Sobrien          nent->dependencies = -1;
255884865Sobrien	}
255984865Sobrien
256084865Sobrien      if (! at_end)
256184865Sobrien	{
256284865Sobrien	  parent = *ptr;
256384865Sobrien	  ptr = &((*ptr)->addl_entries);
256484865Sobrien	  prefix += plen + 1;
256584865Sobrien	}
256684865Sobrien    }
256784865Sobrien
256884865Sobrien  if ((*ptr)->is_terminal)
256984865Sobrien    {
257084865Sobrien      abort ();
257184865Sobrien    }
257284865Sobrien
257384865Sobrien  (*ptr)->is_terminal = 1;
257484865Sobrien  (*ptr)->mask = (ia64_insn)-1;
257584865Sobrien  (*ptr)->bits = opc->opcode;
257684865Sobrien  (*ptr)->dependencies = insert_opcode_dependencies (opc, *ptr);
257784865Sobrien  (*ptr)->order = order;
257884865Sobrien}
257984865Sobrien
258084865Sobrienvoid
258184865Sobrienprint_completer_entry (ent)
258284865Sobrien     struct completer_entry *ent;
258384865Sobrien{
258484865Sobrien  int moffset = 0;
258584865Sobrien  ia64_insn mask = ent->mask, bits = ent->bits;
258684865Sobrien
258784865Sobrien  if (mask != 0)
258884865Sobrien    {
258984865Sobrien      while (! (mask & 1))
259084865Sobrien	{
259184865Sobrien	  moffset++;
259284865Sobrien	  mask = mask >> 1;
259384865Sobrien	  bits = bits >> 1;
259484865Sobrien	}
259584865Sobrien      if (bits & 0xffffffff00000000LL)
259684865Sobrien	{
259784865Sobrien	  abort ();
259884865Sobrien	}
259984865Sobrien    }
260084865Sobrien
260184865Sobrien  printf ("  { 0x%x, 0x%x, %d, %d, %d, %d, %d, %d },\n",
260284865Sobrien	  (int)bits,
260384865Sobrien	  (int)mask,
260484865Sobrien	  ent->name->num,
260584865Sobrien	  ent->alternative != NULL ? ent->alternative->num : -1,
260684865Sobrien	  ent->addl_entries != NULL ? ent->addl_entries->num : -1,
260784865Sobrien	  moffset,
260884865Sobrien	  ent->is_terminal ? 1 : 0,
260984865Sobrien          ent->dependencies);
261084865Sobrien}
261184865Sobrien
261284865Sobrienvoid
261384865Sobrienprint_completer_table ()
261484865Sobrien{
261584865Sobrien  int x;
261684865Sobrien
261784865Sobrien  printf ("static const struct ia64_completer_table\ncompleter_table[] = {\n");
261884865Sobrien  for (x = 0; x < glistlen; x++)
261984865Sobrien    {
262084865Sobrien      print_completer_entry (glist[x]);
262184865Sobrien    }
262284865Sobrien  printf ("};\n\n");
262384865Sobrien}
262484865Sobrien
262584865Sobrienint
262684865Sobrienopcodes_eq (opc1, opc2)
262784865Sobrien     struct ia64_opcode *opc1;
262884865Sobrien     struct ia64_opcode *opc2;
262984865Sobrien{
263084865Sobrien  int x;
263184865Sobrien  int plen1, plen2;
263284865Sobrien
263384865Sobrien  if ((opc1->mask != opc2->mask) || (opc1->type != opc2->type)
263484865Sobrien      || (opc1->num_outputs != opc2->num_outputs)
263584865Sobrien      || (opc1->flags != opc2->flags))
263684865Sobrien    {
263784865Sobrien      return 0;
263884865Sobrien    }
263984865Sobrien  for (x = 0; x < 5; x++)
264084865Sobrien    {
264184865Sobrien      if (opc1->operands[x] != opc2->operands[x])
264284865Sobrien	{
264384865Sobrien	  return 0;
264484865Sobrien	}
264584865Sobrien    }
264684865Sobrien  plen1 = get_prefix_len (opc1->name);
264784865Sobrien  plen2 = get_prefix_len (opc2->name);
264884865Sobrien  if (plen1 == plen2 && (memcmp (opc1->name, opc2->name, plen1) == 0))
264984865Sobrien    {
265084865Sobrien      return 1;
265184865Sobrien    }
265284865Sobrien  return 0;
265384865Sobrien}
265484865Sobrien
265584865Sobrienvoid
265684865Sobrienadd_opcode_entry (opc)
265784865Sobrien     struct ia64_opcode *opc;
265884865Sobrien{
265984865Sobrien  struct main_entry **place;
266084865Sobrien  struct string_entry *name;
266184865Sobrien  char prefix[129];
266284865Sobrien  int found_it = 0;
266384865Sobrien
266484865Sobrien  if (strlen (opc->name) > 128)
266584865Sobrien    {
266684865Sobrien      abort ();
266784865Sobrien    }
266884865Sobrien  place = &maintable;
266984865Sobrien  strcpy (prefix, opc->name);
267084865Sobrien  prefix[get_prefix_len (prefix)] = '\0';
267184865Sobrien  name = insert_string (prefix);
267284865Sobrien
267384865Sobrien  /* Walk the list of opcode table entries.  If it's a new
267484865Sobrien     instruction, allocate and fill in a new entry.  Note
267584865Sobrien     the main table is alphabetical by opcode name. */
267684865Sobrien
267784865Sobrien  while (*place != NULL)
267884865Sobrien    {
267984865Sobrien      if ((*place)->name->num == name->num
268084865Sobrien	  && opcodes_eq ((*place)->opcode, opc))
268184865Sobrien	{
268284865Sobrien	  found_it = 1;
268384865Sobrien	  break;
268484865Sobrien	}
268584865Sobrien      if ((*place)->name->num > name->num)
268684865Sobrien	{
268784865Sobrien	  break;
268884865Sobrien	}
268984865Sobrien      place = &((*place)->next);
269084865Sobrien    }
269184865Sobrien  if (! found_it)
269284865Sobrien    {
269384865Sobrien      struct main_entry *nent = tmalloc (struct main_entry);
269484865Sobrien
269584865Sobrien      nent->name = name;
269684865Sobrien      nent->opcode = opc;
269784865Sobrien      nent->next = *place;
269884865Sobrien      nent->completers = 0;
269984865Sobrien      *place = nent;
270084865Sobrien
270184865Sobrien      if (otlen == ottotlen)
270284865Sobrien        {
270384865Sobrien          ottotlen += 20;
270484865Sobrien          ordered_table = (struct main_entry **)
270584865Sobrien            xrealloc (ordered_table, sizeof (struct main_entry *) * ottotlen);
270684865Sobrien        }
270784865Sobrien      ordered_table[otlen++] = nent;
270884865Sobrien    }
270984865Sobrien
271084865Sobrien  insert_completer_entry (opc, *place, opcode_count++);
271184865Sobrien}
271284865Sobrien
271384865Sobrienvoid
271484865Sobrienprint_main_table ()
271584865Sobrien{
271684865Sobrien  struct main_entry *ptr = maintable;
271784865Sobrien  int index = 0;
271884865Sobrien
271984865Sobrien  printf ("static const struct ia64_main_table\nmain_table[] = {\n");
272084865Sobrien  while (ptr != NULL)
272184865Sobrien    {
272284865Sobrien      printf ("  { %d, %d, %d, 0x",
272384865Sobrien	      ptr->name->num,
272484865Sobrien	      ptr->opcode->type,
272584865Sobrien	      ptr->opcode->num_outputs);
272684865Sobrien      fprintf_vma (stdout, ptr->opcode->opcode);
272784865Sobrien      printf ("ull, 0x");
272884865Sobrien      fprintf_vma (stdout, ptr->opcode->mask);
272984865Sobrien      printf ("ull, { %d, %d, %d, %d, %d }, 0x%x, %d, },\n",
273084865Sobrien	      ptr->opcode->operands[0],
273184865Sobrien	      ptr->opcode->operands[1],
273284865Sobrien	      ptr->opcode->operands[2],
273384865Sobrien	      ptr->opcode->operands[3],
273484865Sobrien	      ptr->opcode->operands[4],
273584865Sobrien	      ptr->opcode->flags,
273684865Sobrien	      ptr->completers->num);
273784865Sobrien
273884865Sobrien      ptr->main_index = index++;
273984865Sobrien
274084865Sobrien      ptr = ptr->next;
274184865Sobrien    }
274284865Sobrien  printf ("};\n\n");
274384865Sobrien}
274484865Sobrien
274584865Sobrienvoid
274684865Sobrienshrink (table)
274784865Sobrien     struct ia64_opcode *table;
274884865Sobrien{
274984865Sobrien  int curr_opcode;
275084865Sobrien
275184865Sobrien  for (curr_opcode = 0; table[curr_opcode].name != NULL; curr_opcode++)
275284865Sobrien    {
275384865Sobrien      add_opcode_entry (table + curr_opcode);
275484865Sobrien    }
275584865Sobrien}
275684865Sobrien
275784865Sobrienint
275884865Sobrienmain (argc, argv)
275984865Sobrien     int argc;
276084865Sobrien     char **argv ATTRIBUTE_UNUSED;
276184865Sobrien{
276284865Sobrien  if (argc > 1)
276384865Sobrien    {
276484865Sobrien      debug = 1;
276584865Sobrien    }
276684865Sobrien
276784865Sobrien  load_insn_classes();
276884865Sobrien  load_dependencies();
276984865Sobrien
277084865Sobrien  shrink (ia64_opcodes_a);
277184865Sobrien  shrink (ia64_opcodes_b);
277284865Sobrien  shrink (ia64_opcodes_f);
277384865Sobrien  shrink (ia64_opcodes_i);
277484865Sobrien  shrink (ia64_opcodes_m);
277584865Sobrien  shrink (ia64_opcodes_x);
277684865Sobrien  shrink (ia64_opcodes_d);
277784865Sobrien
277884865Sobrien  collapse_redundant_completers ();
277984865Sobrien
278084865Sobrien  printf ("/* This file is automatically generated by ia64-gen.  Do not edit! */\n");
278184865Sobrien  print_string_table ();
278284865Sobrien  print_dependency_table ();
278384865Sobrien  print_completer_table ();
278484865Sobrien  print_main_table ();
278584865Sobrien
278684865Sobrien  generate_disassembler ();
278784865Sobrien
278884865Sobrien  exit (0);
278984865Sobrien}
2790