1/* ia64-gen.c -- Generate a shrunk set of opcode tables
2   Copyright 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
3   Free Software Foundation, Inc.
4   Written by Bob Manson, Cygnus Solutions, <manson@cygnus.com>
5
6   This file is part of the GNU opcodes library.
7
8   This library is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3, or (at your option)
11   any later version.
12
13   It is distributed in the hope that it will be useful, but WITHOUT
14   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16   License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this file; see the file COPYING.  If not, write to the
20   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21   02110-1301, USA.  */
22
23
24/* While the ia64-opc-* set of opcode tables are easy to maintain,
25   they waste a tremendous amount of space.  ia64-gen rearranges the
26   instructions into a directed acyclic graph (DAG) of instruction opcodes and
27   their possible completers, as well as compacting the set of strings used.
28
29   The disassembler table consists of a state machine that does
30   branching based on the bits of the opcode being disassembled.  The
31   state encodings have been chosen to minimize the amount of space
32   required.
33
34   The resource table is constructed based on some text dependency tables,
35   which are also easier to maintain than the final representation.  */
36
37#include <stdio.h>
38#include <stdarg.h>
39#include <errno.h>
40
41#include "ansidecl.h"
42#include "libiberty.h"
43#include "safe-ctype.h"
44#include "sysdep.h"
45#include "getopt.h"
46#include "ia64-opc.h"
47#include "ia64-opc-a.c"
48#include "ia64-opc-i.c"
49#include "ia64-opc-m.c"
50#include "ia64-opc-b.c"
51#include "ia64-opc-f.c"
52#include "ia64-opc-x.c"
53#include "ia64-opc-d.c"
54
55#include <libintl.h>
56#define _(String) gettext (String)
57
58/* This is a copy of fprintf_vma from bfd/bfd-in2.h.  We have to use this
59   always, because we might be compiled without BFD64 defined, if configured
60   for a 32-bit target and --enable-targets=all is used.  This will work for
61   both 32-bit and 64-bit hosts.  */
62#define _opcode_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
63#define _opcode_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
64#define opcode_fprintf_vma(s,x) \
65  fprintf ((s), "%08lx%08lx", _opcode_int64_high (x), _opcode_int64_low (x))
66
67const char * program_name = NULL;
68int debug = 0;
69
70#define NELEMS(a) (sizeof (a) / sizeof ((a)[0]))
71#define tmalloc(X) (X *) xmalloc (sizeof (X))
72
73/* The main opcode table entry.  Each entry is a unique combination of
74   name and flags (no two entries in the table compare as being equal
75   via opcodes_eq).  */
76struct main_entry
77{
78  /* The base name of this opcode.  The names of its completers are
79     appended to it to generate the full instruction name.  */
80  struct string_entry *name;
81  /* The base opcode entry.  Which one to use is a fairly arbitrary choice;
82     it uses the first one passed to add_opcode_entry.  */
83  struct ia64_opcode *opcode;
84  /* The list of completers that can be applied to this opcode.  */
85  struct completer_entry *completers;
86  /* Next entry in the chain.  */
87  struct main_entry *next;
88  /* Index in the  main table.  */
89  int main_index;
90} *maintable, **ordered_table;
91
92int otlen = 0;
93int ottotlen = 0;
94int opcode_count = 0;
95
96/* The set of possible completers for an opcode.  */
97struct completer_entry
98{
99  /* This entry's index in the ia64_completer_table[] array.  */
100  int num;
101
102  /* The name of the completer.  */
103  struct string_entry *name;
104
105  /* This entry's parent.  */
106  struct completer_entry *parent;
107
108  /* Set if this is a terminal completer (occurs at the end of an
109     opcode).  */
110  int is_terminal;
111
112  /* An alternative completer.  */
113  struct completer_entry *alternative;
114
115  /* Additional completers that can be appended to this one.  */
116  struct completer_entry *addl_entries;
117
118  /* Before compute_completer_bits () is invoked, this contains the actual
119     instruction opcode for this combination of opcode and completers.
120     Afterwards, it contains those bits that are different from its
121     parent opcode.  */
122  ia64_insn bits;
123
124  /* Bits set to 1 correspond to those bits in this completer's opcode
125     that are different from its parent completer's opcode (or from
126     the base opcode if the entry is the root of the opcode's completer
127     list).  This field is filled in by compute_completer_bits ().  */
128  ia64_insn mask;
129
130  /* Index into the opcode dependency list, or -1 if none.  */
131  int dependencies;
132
133  /* Remember the order encountered in the opcode tables.  */
134  int order;
135};
136
137/* One entry in the disassembler name table.  */
138struct disent
139{
140  /* The index into the ia64_name_dis array for this entry.  */
141  int ournum;
142
143  /* The index into the main_table[] array.  */
144  int insn;
145
146  /* The disassmbly priority of this entry.  */
147  int priority;
148
149  /* The completer_index value for this entry.  */
150  int completer_index;
151
152  /* How many other entries share this decode.  */
153  int nextcnt;
154
155  /* The next entry sharing the same decode.  */
156  struct disent *nexte;
157
158  /* The next entry in the name list.  */
159  struct disent *next_ent;
160} *disinsntable = NULL;
161
162/* A state machine that will eventually be used to generate the
163   disassembler table.  */
164struct bittree
165{
166  struct disent *disent;
167  struct bittree *bits[3]; /* 0, 1, and X (don't care).  */
168  int bits_to_skip;
169  int skip_flag;
170} *bittree;
171
172/* The string table contains all opcodes and completers sorted in
173   alphabetical order.  */
174
175/* One entry in the string table.  */
176struct string_entry
177{
178  /* The index in the ia64_strings[] array for this entry.  */
179  int num;
180  /* And the string.  */
181  char *s;
182} **string_table = NULL;
183
184int strtablen = 0;
185int strtabtotlen = 0;
186
187
188/* Resource dependency entries.  */
189struct rdep
190{
191  char *name;                       /* Resource name.  */
192  unsigned
193    mode:2,                         /* RAW, WAW, or WAR.  */
194    semantics:3;                    /* Dependency semantics.  */
195  char *extra;                      /* Additional semantics info.  */
196  int nchks;
197  int total_chks;                   /* Total #of terminal insns.  */
198  int *chks;                        /* Insn classes which read (RAW), write
199                                       (WAW), or write (WAR) this rsrc.  */
200  int *chknotes;                    /* Dependency notes for each class.  */
201  int nregs;
202  int total_regs;                   /* Total #of terminal insns.  */
203  int *regs;                        /* Insn class which write (RAW), write2
204                                       (WAW), or read (WAR) this rsrc.  */
205  int *regnotes;                    /* Dependency notes for each class.  */
206
207  int waw_special;                  /* Special WAW dependency note.  */
208} **rdeps = NULL;
209
210static int rdepslen = 0;
211static int rdepstotlen = 0;
212
213/* Array of all instruction classes.  */
214struct iclass
215{
216  char *name;                       /* Instruction class name.  */
217  int is_class;                     /* Is a class, not a terminal.  */
218  int nsubs;
219  int *subs;                        /* Other classes within this class.  */
220  int nxsubs;
221  int xsubs[4];                     /* Exclusions.  */
222  char *comment;                    /* Optional comment.  */
223  int note;                         /* Optional note.  */
224  int terminal_resolved;            /* Did we match this with anything?  */
225  int orphan;                       /* Detect class orphans.  */
226} **ics = NULL;
227
228static int iclen = 0;
229static int ictotlen = 0;
230
231/* An opcode dependency (chk/reg pair of dependency lists).  */
232struct opdep
233{
234  int chk;                          /* index into dlists */
235  int reg;                          /* index into dlists */
236} **opdeps;
237
238static int opdeplen = 0;
239static int opdeptotlen = 0;
240
241/* A generic list of dependencies w/notes encoded.  These may be shared.  */
242struct deplist
243{
244  int len;
245  unsigned short *deps;
246} **dlists;
247
248static int dlistlen = 0;
249static int dlisttotlen = 0;
250
251
252static void fail (const char *, ...) ATTRIBUTE_PRINTF_1;
253static void warn (const char *, ...) ATTRIBUTE_PRINTF_1;
254static struct rdep * insert_resource (const char *, enum ia64_dependency_mode);
255static int  deplist_equals (struct deplist *, struct deplist *);
256static short insert_deplist (int, unsigned short *);
257static short insert_dependencies (int, unsigned short *, int, unsigned short *);
258static void  mark_used (struct iclass *, int);
259static int  fetch_insn_class (const char *, int);
260static int  sub_compare (const void *, const void *);
261static void load_insn_classes (void);
262static void parse_resource_users (const char *, int **, int *, int **);
263static int  parse_semantics (char *);
264static void add_dep (const char *, const char *, const char *, int, int, char *, int);
265static void load_depfile (const char *, enum ia64_dependency_mode);
266static void load_dependencies (void);
267static int  irf_operand (int, const char *);
268static int  in_iclass_mov_x (struct ia64_opcode *, struct iclass *, const char *, const char *);
269static int  in_iclass (struct ia64_opcode *, struct iclass *, const char *, const char *, int *);
270static int  lookup_regindex (const char *, int);
271static int  lookup_specifier (const char *);
272static void print_dependency_table (void);
273static struct string_entry * insert_string (char *);
274static void gen_dis_table (struct bittree *);
275static void print_dis_table (void);
276static void generate_disassembler (void);
277static void print_string_table (void);
278static int  completer_entries_eq (struct completer_entry *, struct completer_entry *);
279static struct completer_entry * insert_gclist (struct completer_entry *);
280static int  get_prefix_len (const char *);
281static void compute_completer_bits (struct main_entry *, struct completer_entry *);
282static void collapse_redundant_completers (void);
283static int  insert_opcode_dependencies (struct ia64_opcode *, struct completer_entry *);
284static void insert_completer_entry (struct ia64_opcode *, struct main_entry *, int);
285static void print_completer_entry (struct completer_entry *);
286static void print_completer_table (void);
287static int  opcodes_eq (struct ia64_opcode *, struct ia64_opcode *);
288static void add_opcode_entry (struct ia64_opcode *);
289static void print_main_table (void);
290static void shrink (struct ia64_opcode *);
291static void print_version (void);
292static void usage (FILE *, int);
293static void finish_distable (void);
294static void insert_bit_table_ent (struct bittree *, int, ia64_insn, ia64_insn, int, int, int);
295static void add_dis_entry (struct bittree *, ia64_insn, ia64_insn, int, struct completer_entry *, int);
296static void compact_distree (struct bittree *);
297static struct bittree * make_bittree_entry (void);
298static struct disent * add_dis_table_ent (struct disent *, int, int, int);
299
300
301static void
302fail (const char *message, ...)
303{
304  va_list args;
305
306  va_start (args, message);
307  fprintf (stderr, _("%s: Error: "), program_name);
308  vfprintf (stderr, message, args);
309  va_end (args);
310  xexit (1);
311}
312
313static void
314warn (const char *message, ...)
315{
316  va_list args;
317
318  va_start (args, message);
319
320  fprintf (stderr, _("%s: Warning: "), program_name);
321  vfprintf (stderr, message, args);
322  va_end (args);
323}
324
325/* Add NAME to the resource table, where TYPE is RAW or WAW.  */
326static struct rdep *
327insert_resource (const char *name, enum ia64_dependency_mode type)
328{
329  if (rdepslen == rdepstotlen)
330    {
331      rdepstotlen += 20;
332      rdeps = (struct rdep **)
333        xrealloc (rdeps, sizeof(struct rdep **) * rdepstotlen);
334    }
335  rdeps[rdepslen] = tmalloc(struct rdep);
336  memset((void *)rdeps[rdepslen], 0, sizeof(struct rdep));
337  rdeps[rdepslen]->name = xstrdup (name);
338  rdeps[rdepslen]->mode = type;
339  rdeps[rdepslen]->waw_special = 0;
340
341  return rdeps[rdepslen++];
342}
343
344/* Are the lists of dependency indexes equivalent?  */
345static int
346deplist_equals (struct deplist *d1, struct deplist *d2)
347{
348  int i;
349
350  if (d1->len != d2->len)
351    return 0;
352
353  for (i = 0; i < d1->len; i++)
354    if (d1->deps[i] != d2->deps[i])
355      return 0;
356
357  return 1;
358}
359
360/* Add the list of dependencies to the list of dependency lists.  */
361static short
362insert_deplist (int count, unsigned short *deps)
363{
364  /* Sort the list, then see if an equivalent list exists already.
365     this results in a much smaller set of dependency lists.  */
366  struct deplist *list;
367  char set[0x10000];
368  int i;
369
370  memset ((void *)set, 0, sizeof (set));
371  for (i = 0; i < count; i++)
372    set[deps[i]] = 1;
373
374  count = 0;
375  for (i = 0; i < (int) sizeof (set); i++)
376    if (set[i])
377      ++count;
378
379  list = tmalloc (struct deplist);
380  list->len = count;
381  list->deps = (unsigned short *) malloc (sizeof (unsigned short) * count);
382
383  for (i = 0, count = 0; i < (int) sizeof (set); i++)
384    if (set[i])
385      list->deps[count++] = i;
386
387  /* Does this list exist already?  */
388  for (i = 0; i < dlistlen; i++)
389    if (deplist_equals (list, dlists[i]))
390      {
391	free (list->deps);
392	free (list);
393	return i;
394      }
395
396  if (dlistlen == dlisttotlen)
397    {
398      dlisttotlen += 20;
399      dlists = (struct deplist **)
400        xrealloc (dlists, sizeof(struct deplist **) * dlisttotlen);
401    }
402  dlists[dlistlen] = list;
403
404  return dlistlen++;
405}
406
407/* Add the given pair of dependency lists to the opcode dependency list.  */
408static short
409insert_dependencies (int nchks, unsigned short *chks,
410                     int nregs, unsigned short *regs)
411{
412  struct opdep *pair;
413  int i;
414  int regind = -1;
415  int chkind = -1;
416
417  if (nregs > 0)
418    regind = insert_deplist (nregs, regs);
419  if (nchks > 0)
420    chkind = insert_deplist (nchks, chks);
421
422  for (i = 0; i < opdeplen; i++)
423    if (opdeps[i]->chk == chkind
424	&& opdeps[i]->reg == regind)
425      return i;
426
427  pair = tmalloc (struct opdep);
428  pair->chk = chkind;
429  pair->reg = regind;
430
431  if (opdeplen == opdeptotlen)
432    {
433      opdeptotlen += 20;
434      opdeps = (struct opdep **)
435        xrealloc (opdeps, sizeof(struct opdep **) * opdeptotlen);
436    }
437  opdeps[opdeplen] = pair;
438
439  return opdeplen++;
440}
441
442static void
443mark_used (struct iclass *ic, int clear_terminals)
444{
445  int i;
446
447  ic->orphan = 0;
448  if (clear_terminals)
449    ic->terminal_resolved = 1;
450
451  for (i = 0; i < ic->nsubs; i++)
452    mark_used (ics[ic->subs[i]], clear_terminals);
453
454  for (i = 0; i < ic->nxsubs; i++)
455    mark_used (ics[ic->xsubs[i]], clear_terminals);
456}
457
458/* Look up an instruction class; if CREATE make a new one if none found;
459   returns the index into the insn class array.  */
460static int
461fetch_insn_class (const char *full_name, int create)
462{
463  char *name;
464  char *notestr;
465  char *xsect;
466  char *comment;
467  int i, note = 0;
468  int ind;
469  int is_class = 0;
470
471  if (CONST_STRNEQ (full_name, "IC:"))
472    {
473      name = xstrdup (full_name + 3);
474      is_class = 1;
475    }
476  else
477    name = xstrdup (full_name);
478
479  if ((xsect = strchr(name, '\\')) != NULL)
480    is_class = 1;
481  if ((comment = strchr(name, '[')) != NULL)
482    is_class = 1;
483  if ((notestr = strchr(name, '+')) != NULL)
484    is_class = 1;
485
486  /* If it is a composite class, then ignore comments and notes that come after
487     the '\\', since they don't apply to the part we are decoding now.  */
488  if (xsect)
489    {
490      if (comment > xsect)
491	comment = 0;
492      if (notestr > xsect)
493	notestr = 0;
494    }
495
496  if (notestr)
497    {
498      char *nextnotestr;
499
500      note = atoi (notestr + 1);
501      if ((nextnotestr = strchr (notestr + 1, '+')) != NULL)
502        {
503          if (strcmp (notestr, "+1+13") == 0)
504            note = 13;
505          else if (!xsect || nextnotestr < xsect)
506            warn (_("multiple note %s not handled\n"), notestr);
507        }
508    }
509
510  /* If it's a composite class, leave the notes and comments in place so that
511     we have a unique name for the composite class.  Otherwise, we remove
512     them.  */
513  if (!xsect)
514    {
515      if (notestr)
516        *notestr = 0;
517      if (comment)
518        *comment = 0;
519    }
520
521  for (i = 0; i < iclen; i++)
522    if (strcmp (name, ics[i]->name) == 0
523        && ((comment == NULL && ics[i]->comment == NULL)
524            || (comment != NULL && ics[i]->comment != NULL
525                && strncmp (ics[i]->comment, comment,
526                            strlen (ics[i]->comment)) == 0))
527        && note == ics[i]->note)
528      return i;
529
530  if (!create)
531    return -1;
532
533  /* Doesn't exist, so make a new one.  */
534  if (iclen == ictotlen)
535    {
536      ictotlen += 20;
537      ics = (struct iclass **)
538        xrealloc (ics, (ictotlen) * sizeof (struct iclass *));
539    }
540
541  ind = iclen++;
542  ics[ind] = tmalloc (struct iclass);
543  memset ((void *)ics[ind], 0, sizeof (struct iclass));
544  ics[ind]->name = xstrdup (name);
545  ics[ind]->is_class = is_class;
546  ics[ind]->orphan = 1;
547
548  if (comment)
549    {
550      ics[ind]->comment = xstrdup (comment + 1);
551      ics[ind]->comment[strlen (ics[ind]->comment)-1] = 0;
552    }
553
554  if (notestr)
555    ics[ind]->note = note;
556
557  /* If it's a composite class, there's a comment or note, look for an
558     existing class or terminal with the same name.  */
559  if ((xsect || comment || notestr) && is_class)
560    {
561      /* First, populate with the class we're based on.  */
562      char *subname = name;
563
564      if (xsect)
565        *xsect = 0;
566      else if (comment)
567        *comment = 0;
568      else if (notestr)
569        *notestr = 0;
570
571      ics[ind]->nsubs = 1;
572      ics[ind]->subs = tmalloc(int);
573      ics[ind]->subs[0] = fetch_insn_class (subname, 1);;
574    }
575
576  while (xsect)
577    {
578      char *subname = xsect + 1;
579
580      xsect = strchr (subname, '\\');
581      if (xsect)
582        *xsect = 0;
583      ics[ind]->xsubs[ics[ind]->nxsubs] = fetch_insn_class (subname,1);
584      ics[ind]->nxsubs++;
585    }
586  free (name);
587
588  return ind;
589}
590
591/* For sorting a class's sub-class list only; make sure classes appear before
592   terminals.  */
593static int
594sub_compare (const void *e1, const void *e2)
595{
596  struct iclass *ic1 = ics[*(int *)e1];
597  struct iclass *ic2 = ics[*(int *)e2];
598
599  if (ic1->is_class)
600    {
601      if (!ic2->is_class)
602        return -1;
603    }
604  else if (ic2->is_class)
605    return 1;
606
607  return strcmp (ic1->name, ic2->name);
608}
609
610static void
611load_insn_classes (void)
612{
613  FILE *fp = fopen ("ia64-ic.tbl", "r");
614  char buf[2048];
615
616  if (fp == NULL)
617    fail (_("can't find ia64-ic.tbl for reading\n"));
618
619  /* Discard first line.  */
620  fgets (buf, sizeof(buf), fp);
621
622  while (!feof (fp))
623    {
624      int iclass;
625      char *name;
626      char *tmp;
627
628      if (fgets (buf, sizeof (buf), fp) == NULL)
629        break;
630
631      while (ISSPACE (buf[strlen (buf) - 1]))
632        buf[strlen (buf) - 1] = '\0';
633
634      name = tmp = buf;
635      while (*tmp != ';')
636        {
637          ++tmp;
638          if (tmp == buf + sizeof (buf))
639            abort ();
640        }
641      *tmp++ = '\0';
642
643      iclass = fetch_insn_class (name, 1);
644      ics[iclass]->is_class = 1;
645
646      if (strcmp (name, "none") == 0)
647        {
648          ics[iclass]->is_class = 0;
649          ics[iclass]->terminal_resolved = 1;
650          continue;
651        }
652
653      /* For this class, record all sub-classes.  */
654      while (*tmp)
655        {
656          char *subname;
657          int sub;
658
659          while (*tmp && ISSPACE (*tmp))
660            {
661              ++tmp;
662              if (tmp == buf + sizeof (buf))
663                abort ();
664            }
665          subname = tmp;
666          while (*tmp && *tmp != ',')
667            {
668              ++tmp;
669              if (tmp == buf + sizeof (buf))
670                abort ();
671            }
672          if (*tmp == ',')
673            *tmp++ = '\0';
674
675          ics[iclass]->subs = (int *)
676            xrealloc ((void *)ics[iclass]->subs,
677		      (ics[iclass]->nsubs + 1) * sizeof (int));
678
679          sub = fetch_insn_class (subname, 1);
680          ics[iclass]->subs = (int *)
681            xrealloc (ics[iclass]->subs, (ics[iclass]->nsubs + 1) * sizeof (int));
682          ics[iclass]->subs[ics[iclass]->nsubs++] = sub;
683        }
684
685      /* Make sure classes come before terminals.  */
686      qsort ((void *)ics[iclass]->subs,
687             ics[iclass]->nsubs, sizeof(int), sub_compare);
688    }
689  fclose (fp);
690
691  if (debug)
692    printf ("%d classes\n", iclen);
693}
694
695/* Extract the insn classes from the given line.  */
696static void
697parse_resource_users (ref, usersp, nusersp, notesp)
698  const char *ref;
699  int **usersp;
700  int *nusersp;
701  int **notesp;
702{
703  int c;
704  char *line = xstrdup (ref);
705  char *tmp = line;
706  int *users = *usersp;
707  int count = *nusersp;
708  int *notes = *notesp;
709
710  c = *tmp;
711  while (c != 0)
712    {
713      char *notestr;
714      int note;
715      char *xsect;
716      int iclass;
717      int create = 0;
718      char *name;
719
720      while (ISSPACE (*tmp))
721        ++tmp;
722      name = tmp;
723      while (*tmp && *tmp != ',')
724        ++tmp;
725      c = *tmp;
726      *tmp++ = '\0';
727
728      xsect = strchr (name, '\\');
729      if ((notestr = strstr (name, "+")) != NULL)
730        {
731          char *nextnotestr;
732
733          note = atoi (notestr + 1);
734          if ((nextnotestr = strchr (notestr + 1, '+')) != NULL)
735            {
736              /* Note 13 always implies note 1.  */
737              if (strcmp (notestr, "+1+13") == 0)
738                note = 13;
739              else if (!xsect || nextnotestr < xsect)
740                warn (_("multiple note %s not handled\n"), notestr);
741            }
742          if (!xsect)
743            *notestr = '\0';
744        }
745      else
746        note = 0;
747
748      /* All classes are created when the insn class table is parsed;
749         Individual instructions might not appear until the dependency tables
750         are read.  Only create new classes if it's *not* an insn class,
751         or if it's a composite class (which wouldn't necessarily be in the IC
752         table).  */
753      if (! CONST_STRNEQ (name, "IC:") || xsect != NULL)
754        create = 1;
755
756      iclass = fetch_insn_class (name, create);
757      if (iclass != -1)
758        {
759          users = (int *)
760            xrealloc ((void *) users,(count + 1) * sizeof (int));
761          notes = (int *)
762            xrealloc ((void *) notes,(count + 1) * sizeof (int));
763          notes[count] = note;
764          users[count++] = iclass;
765          mark_used (ics[iclass], 0);
766        }
767      else if (debug)
768	printf("Class %s not found\n", name);
769    }
770  /* Update the return values.  */
771  *usersp = users;
772  *nusersp = count;
773  *notesp = notes;
774
775  free (line);
776}
777
778static int
779parse_semantics (char *sem)
780{
781  if (strcmp (sem, "none") == 0)
782    return IA64_DVS_NONE;
783  else if (strcmp (sem, "implied") == 0)
784    return IA64_DVS_IMPLIED;
785  else if (strcmp (sem, "impliedF") == 0)
786    return IA64_DVS_IMPLIEDF;
787  else if (strcmp (sem, "data") == 0)
788    return IA64_DVS_DATA;
789  else if (strcmp (sem, "instr") == 0)
790    return IA64_DVS_INSTR;
791  else if (strcmp (sem, "specific") == 0)
792    return IA64_DVS_SPECIFIC;
793  else if (strcmp (sem, "stop") == 0)
794    return IA64_DVS_STOP;
795  else
796    return IA64_DVS_OTHER;
797}
798
799static void
800add_dep (const char *name, const char *chk, const char *reg,
801         int semantics, int mode, char *extra, int flag)
802{
803  struct rdep *rs;
804
805  rs = insert_resource (name, mode);
806
807  parse_resource_users (chk, &rs->chks, &rs->nchks, &rs->chknotes);
808  parse_resource_users (reg, &rs->regs, &rs->nregs, &rs->regnotes);
809
810  rs->semantics = semantics;
811  rs->extra = extra;
812  rs->waw_special = flag;
813}
814
815static void
816load_depfile (const char *filename, enum ia64_dependency_mode mode)
817{
818  FILE *fp = fopen (filename, "r");
819  char buf[1024];
820
821  if (fp == NULL)
822    fail (_("can't find %s for reading\n"), filename);
823
824  fgets (buf, sizeof(buf), fp);
825  while (!feof (fp))
826    {
827      char *name, *tmp;
828      int semantics;
829      char *extra;
830      char *regp, *chkp;
831
832      if (fgets (buf, sizeof(buf), fp) == NULL)
833        break;
834
835      while (ISSPACE (buf[strlen (buf) - 1]))
836        buf[strlen (buf) - 1] = '\0';
837
838      name = tmp = buf;
839      while (*tmp != ';')
840        ++tmp;
841      *tmp++ = '\0';
842
843      while (ISSPACE (*tmp))
844        ++tmp;
845      regp = tmp;
846      tmp = strchr (tmp, ';');
847      if (!tmp)
848        abort ();
849      *tmp++ = 0;
850      while (ISSPACE (*tmp))
851        ++tmp;
852      chkp = tmp;
853      tmp = strchr (tmp, ';');
854      if (!tmp)
855        abort ();
856      *tmp++ = 0;
857      while (ISSPACE (*tmp))
858        ++tmp;
859      semantics = parse_semantics (tmp);
860      extra = semantics == IA64_DVS_OTHER ? xstrdup (tmp) : NULL;
861
862      /* For WAW entries, if the chks and regs differ, we need to enter the
863         entries in both positions so that the tables will be parsed properly,
864         without a lot of extra work.  */
865      if (mode == IA64_DV_WAW && strcmp (regp, chkp) != 0)
866        {
867          add_dep (name, chkp, regp, semantics, mode, extra, 0);
868          add_dep (name, regp, chkp, semantics, mode, extra, 1);
869        }
870      else
871        {
872          add_dep (name, chkp, regp, semantics, mode, extra, 0);
873        }
874    }
875  fclose (fp);
876}
877
878static void
879load_dependencies (void)
880{
881  load_depfile ("ia64-raw.tbl", IA64_DV_RAW);
882  load_depfile ("ia64-waw.tbl", IA64_DV_WAW);
883  load_depfile ("ia64-war.tbl", IA64_DV_WAR);
884
885  if (debug)
886    printf ("%d RAW/WAW/WAR dependencies\n", rdepslen);
887}
888
889/* Is the given operand an indirect register file operand?  */
890static int
891irf_operand (int op, const char *field)
892{
893  if (!field)
894    {
895      return op == IA64_OPND_RR_R3 || op == IA64_OPND_DBR_R3
896        || op == IA64_OPND_IBR_R3  || op == IA64_OPND_PKR_R3
897	|| op == IA64_OPND_PMC_R3  || op == IA64_OPND_PMD_R3
898	|| op == IA64_OPND_MSR_R3 || op == IA64_OPND_CPUID_R3;
899    }
900  else
901    {
902      return ((op == IA64_OPND_RR_R3 && strstr (field, "rr"))
903              || (op == IA64_OPND_DBR_R3 && strstr (field, "dbr"))
904              || (op == IA64_OPND_IBR_R3 && strstr (field, "ibr"))
905              || (op == IA64_OPND_PKR_R3 && strstr (field, "pkr"))
906              || (op == IA64_OPND_PMC_R3 && strstr (field, "pmc"))
907              || (op == IA64_OPND_PMD_R3 && strstr (field, "pmd"))
908              || (op == IA64_OPND_MSR_R3 && strstr (field, "msr"))
909              || (op == IA64_OPND_CPUID_R3 && strstr (field, "cpuid")));
910    }
911}
912
913/* Handle mov_ar, mov_br, mov_cr, mov_indirect, mov_ip, mov_pr, mov_psr, and
914   mov_um insn classes.  */
915static int
916in_iclass_mov_x (struct ia64_opcode *idesc, struct iclass *ic,
917                 const char *format, const char *field)
918{
919  int plain_mov = strcmp (idesc->name, "mov") == 0;
920
921  if (!format)
922    return 0;
923
924  switch (ic->name[4])
925    {
926    default:
927      abort ();
928    case 'a':
929      {
930        int i = strcmp (idesc->name, "mov.i") == 0;
931        int m = strcmp (idesc->name, "mov.m") == 0;
932        int i2627 = i && idesc->operands[0] == IA64_OPND_AR3;
933        int i28 = i && idesc->operands[1] == IA64_OPND_AR3;
934        int m2930 = m && idesc->operands[0] == IA64_OPND_AR3;
935        int m31 = m && idesc->operands[1] == IA64_OPND_AR3;
936        int pseudo0 = plain_mov && idesc->operands[1] == IA64_OPND_AR3;
937        int pseudo1 = plain_mov && idesc->operands[0] == IA64_OPND_AR3;
938
939        /* IC:mov ar */
940        if (i2627)
941          return strstr (format, "I26") || strstr (format, "I27");
942        if (i28)
943          return strstr (format, "I28") != NULL;
944        if (m2930)
945          return strstr (format, "M29") || strstr (format, "M30");
946        if (m31)
947          return strstr (format, "M31") != NULL;
948        if (pseudo0 || pseudo1)
949          return 1;
950      }
951      break;
952    case 'b':
953      {
954        int i21 = idesc->operands[0] == IA64_OPND_B1;
955        int i22 = plain_mov && idesc->operands[1] == IA64_OPND_B2;
956        if (i22)
957          return strstr (format, "I22") != NULL;
958        if (i21)
959          return strstr (format, "I21") != NULL;
960      }
961      break;
962    case 'c':
963      {
964        int m32 = plain_mov && idesc->operands[0] == IA64_OPND_CR3;
965        int m33 = plain_mov && idesc->operands[1] == IA64_OPND_CR3;
966        if (m32)
967          return strstr (format, "M32") != NULL;
968        if (m33)
969          return strstr (format, "M33") != NULL;
970      }
971      break;
972    case 'i':
973      if (ic->name[5] == 'n')
974        {
975          int m42 = plain_mov && irf_operand (idesc->operands[0], field);
976          int m43 = plain_mov && irf_operand (idesc->operands[1], field);
977          if (m42)
978            return strstr (format, "M42") != NULL;
979          if (m43)
980            return strstr (format, "M43") != NULL;
981        }
982      else if (ic->name[5] == 'p')
983        {
984          return idesc->operands[1] == IA64_OPND_IP;
985        }
986      else
987        abort ();
988      break;
989    case 'p':
990      if (ic->name[5] == 'r')
991        {
992          int i25 = plain_mov && idesc->operands[1] == IA64_OPND_PR;
993          int i23 = plain_mov && idesc->operands[0] == IA64_OPND_PR;
994          int i24 = plain_mov && idesc->operands[0] == IA64_OPND_PR_ROT;
995          if (i23)
996            return strstr (format, "I23") != NULL;
997          if (i24)
998            return strstr (format, "I24") != NULL;
999          if (i25)
1000            return strstr (format, "I25") != NULL;
1001        }
1002      else if (ic->name[5] == 's')
1003        {
1004          int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_L;
1005          int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR;
1006          if (m35)
1007            return strstr (format, "M35") != NULL;
1008          if (m36)
1009            return strstr (format, "M36") != NULL;
1010        }
1011      else
1012        abort ();
1013      break;
1014    case 'u':
1015      {
1016        int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_UM;
1017        int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR_UM;
1018        if (m35)
1019          return strstr (format, "M35") != NULL;
1020        if (m36)
1021          return strstr (format, "M36") != NULL;
1022      }
1023      break;
1024    }
1025  return 0;
1026}
1027
1028/* Is the given opcode in the given insn class?  */
1029static int
1030in_iclass (struct ia64_opcode *idesc, struct iclass *ic,
1031	   const char *format, const char *field, int *notep)
1032{
1033  int i;
1034  int resolved = 0;
1035
1036  if (ic->comment)
1037    {
1038      if (CONST_STRNEQ (ic->comment, "Format"))
1039        {
1040          /* Assume that the first format seen is the most restrictive, and
1041             only keep a later one if it looks like it's more restrictive.  */
1042          if (format)
1043            {
1044              if (strlen (ic->comment) < strlen (format))
1045                {
1046                  warn (_("most recent format '%s'\nappears more restrictive than '%s'\n"),
1047			ic->comment, format);
1048                  format = ic->comment;
1049                }
1050            }
1051          else
1052            format = ic->comment;
1053        }
1054      else if (CONST_STRNEQ (ic->comment, "Field"))
1055        {
1056          if (field)
1057            warn (_("overlapping field %s->%s\n"),
1058		  ic->comment, field);
1059          field = ic->comment;
1060        }
1061    }
1062
1063  /* An insn class matches anything that is the same followed by completers,
1064     except when the absence and presence of completers constitutes different
1065     instructions.  */
1066  if (ic->nsubs == 0 && ic->nxsubs == 0)
1067    {
1068      int is_mov = CONST_STRNEQ (idesc->name, "mov");
1069      int plain_mov = strcmp (idesc->name, "mov") == 0;
1070      int len = strlen(ic->name);
1071
1072      resolved = ((strncmp (ic->name, idesc->name, len) == 0)
1073                  && (idesc->name[len] == '\0'
1074                      || idesc->name[len] == '.'));
1075
1076      /* All break, nop, and hint variations must match exactly.  */
1077      if (resolved &&
1078          (strcmp (ic->name, "break") == 0
1079           || strcmp (ic->name, "nop") == 0
1080	   || strcmp (ic->name, "hint") == 0))
1081        resolved = strcmp (ic->name, idesc->name) == 0;
1082
1083      /* Assume restrictions in the FORMAT/FIELD negate resolution,
1084         unless specifically allowed by clauses in this block.  */
1085      if (resolved && field)
1086        {
1087          /* Check Field(sf)==sN against opcode sN.  */
1088          if (strstr(field, "(sf)==") != NULL)
1089            {
1090              char *sf;
1091
1092              if ((sf = strstr (idesc->name, ".s")) != 0)
1093		resolved = strcmp (sf + 1, strstr (field, "==") + 2) == 0;
1094            }
1095          /* Check Field(lftype)==XXX.  */
1096          else if (strstr (field, "(lftype)") != NULL)
1097            {
1098              if (strstr (idesc->name, "fault") != NULL)
1099                resolved = strstr (field, "fault") != NULL;
1100              else
1101                resolved = strstr (field, "fault") == NULL;
1102            }
1103          /* Handle Field(ctype)==XXX.  */
1104          else if (strstr (field, "(ctype)") != NULL)
1105            {
1106              if (strstr (idesc->name, "or.andcm"))
1107                resolved = strstr (field, "or.andcm") != NULL;
1108              else if (strstr (idesc->name, "and.orcm"))
1109                resolved = strstr (field, "and.orcm") != NULL;
1110              else if (strstr (idesc->name, "orcm"))
1111                resolved = strstr (field, "or orcm") != NULL;
1112              else if (strstr (idesc->name, "or"))
1113                resolved = strstr (field, "or orcm") != NULL;
1114              else if (strstr (idesc->name, "andcm"))
1115                resolved = strstr (field, "and andcm") != NULL;
1116              else if (strstr (idesc->name, "and"))
1117                resolved = strstr (field, "and andcm") != NULL;
1118              else if (strstr (idesc->name, "unc"))
1119                resolved = strstr (field, "unc") != NULL;
1120              else
1121                resolved = strcmp (field, "Field(ctype)==") == 0;
1122            }
1123        }
1124
1125      if (resolved && format)
1126        {
1127          if (CONST_STRNEQ (idesc->name, "dep")
1128                   && strstr (format, "I13") != NULL)
1129            resolved = idesc->operands[1] == IA64_OPND_IMM8;
1130          else if (CONST_STRNEQ (idesc->name, "chk")
1131                   && strstr (format, "M21") != NULL)
1132            resolved = idesc->operands[0] == IA64_OPND_F2;
1133          else if (CONST_STRNEQ (idesc->name, "lfetch"))
1134            resolved = (strstr (format, "M14 M15") != NULL
1135                        && (idesc->operands[1] == IA64_OPND_R2
1136                            || idesc->operands[1] == IA64_OPND_IMM9b));
1137          else if (CONST_STRNEQ (idesc->name, "br.call")
1138                   && strstr (format, "B5") != NULL)
1139            resolved = idesc->operands[1] == IA64_OPND_B2;
1140          else if (CONST_STRNEQ (idesc->name, "br.call")
1141                   && strstr (format, "B3") != NULL)
1142            resolved = idesc->operands[1] == IA64_OPND_TGT25c;
1143          else if (CONST_STRNEQ (idesc->name, "brp")
1144                   && strstr (format, "B7") != NULL)
1145            resolved = idesc->operands[0] == IA64_OPND_B2;
1146          else if (strcmp (ic->name, "invala") == 0)
1147            resolved = strcmp (idesc->name, ic->name) == 0;
1148	  else if (CONST_STRNEQ (idesc->name, "st")
1149		   && (strstr (format, "M5") != NULL
1150		       || strstr (format, "M10") != NULL))
1151	    resolved = idesc->flags & IA64_OPCODE_POSTINC;
1152	  else if (CONST_STRNEQ (idesc->name, "ld")
1153		   && (strstr (format, "M2 M3") != NULL
1154		       || strstr (format, "M12") != NULL
1155		       || strstr (format, "M7 M8") != NULL))
1156	    resolved = idesc->flags & IA64_OPCODE_POSTINC;
1157          else
1158            resolved = 0;
1159        }
1160
1161      /* Misc brl variations ('.cond' is optional);
1162         plain brl matches brl.cond.  */
1163      if (!resolved
1164          && (strcmp (idesc->name, "brl") == 0
1165              || CONST_STRNEQ (idesc->name, "brl."))
1166          && strcmp (ic->name, "brl.cond") == 0)
1167        {
1168          resolved = 1;
1169        }
1170
1171      /* Misc br variations ('.cond' is optional).  */
1172      if (!resolved
1173          && (strcmp (idesc->name, "br") == 0
1174              || CONST_STRNEQ (idesc->name, "br."))
1175          && strcmp (ic->name, "br.cond") == 0)
1176        {
1177          if (format)
1178            resolved = (strstr (format, "B4") != NULL
1179                        && idesc->operands[0] == IA64_OPND_B2)
1180              || (strstr (format, "B1") != NULL
1181                  && idesc->operands[0] == IA64_OPND_TGT25c);
1182          else
1183            resolved = 1;
1184        }
1185
1186      /* probe variations.  */
1187      if (!resolved && CONST_STRNEQ (idesc->name, "probe"))
1188        {
1189          resolved = strcmp (ic->name, "probe") == 0
1190            && !((strstr (idesc->name, "fault") != NULL)
1191                 ^ (format && strstr (format, "M40") != NULL));
1192        }
1193
1194      /* mov variations.  */
1195      if (!resolved && is_mov)
1196        {
1197          if (plain_mov)
1198            {
1199              /* mov alias for fmerge.  */
1200              if (strcmp (ic->name, "fmerge") == 0)
1201                {
1202                  resolved = idesc->operands[0] == IA64_OPND_F1
1203                    && idesc->operands[1] == IA64_OPND_F3;
1204                }
1205              /* mov alias for adds (r3 or imm14).  */
1206              else if (strcmp (ic->name, "adds") == 0)
1207                {
1208                  resolved = (idesc->operands[0] == IA64_OPND_R1
1209                              && (idesc->operands[1] == IA64_OPND_R3
1210                                  || (idesc->operands[1] == IA64_OPND_IMM14)));
1211                }
1212              /* mov alias for addl.  */
1213              else if (strcmp (ic->name, "addl") == 0)
1214                {
1215                  resolved = idesc->operands[0] == IA64_OPND_R1
1216                    && idesc->operands[1] == IA64_OPND_IMM22;
1217                }
1218            }
1219
1220          /* Some variants of mov and mov.[im].  */
1221          if (!resolved && CONST_STRNEQ (ic->name, "mov_"))
1222	    resolved = in_iclass_mov_x (idesc, ic, format, field);
1223        }
1224
1225      /* Keep track of this so we can flag any insn classes which aren't
1226         mapped onto at least one real insn.  */
1227      if (resolved)
1228	ic->terminal_resolved = 1;
1229    }
1230  else for (i = 0; i < ic->nsubs; i++)
1231    {
1232      if (in_iclass (idesc, ics[ic->subs[i]], format, field, notep))
1233        {
1234          int j;
1235
1236          for (j = 0; j < ic->nxsubs; j++)
1237	    if (in_iclass (idesc, ics[ic->xsubs[j]], NULL, NULL, NULL))
1238	      return 0;
1239
1240          if (debug > 1)
1241            printf ("%s is in IC %s\n", idesc->name, ic->name);
1242
1243          resolved = 1;
1244          break;
1245        }
1246    }
1247
1248  /* If it's in this IC, add the IC note (if any) to the insn.  */
1249  if (resolved)
1250    {
1251      if (ic->note && notep)
1252        {
1253          if (*notep && *notep != ic->note)
1254	    warn (_("overwriting note %d with note %d (IC:%s)\n"),
1255		  *notep, ic->note, ic->name);
1256
1257          *notep = ic->note;
1258        }
1259    }
1260
1261  return resolved;
1262}
1263
1264
1265static int
1266lookup_regindex (const char *name, int specifier)
1267{
1268  switch (specifier)
1269    {
1270    case IA64_RS_ARX:
1271      if (strstr (name, "[RSC]"))
1272        return 16;
1273      if (strstr (name, "[BSP]"))
1274        return 17;
1275      else if (strstr (name, "[BSPSTORE]"))
1276        return 18;
1277      else if (strstr (name, "[RNAT]"))
1278        return 19;
1279      else if (strstr (name, "[FCR]"))
1280        return 21;
1281      else if (strstr (name, "[EFLAG]"))
1282        return 24;
1283      else if (strstr (name, "[CSD]"))
1284        return 25;
1285      else if (strstr (name, "[SSD]"))
1286        return 26;
1287      else if (strstr (name, "[CFLG]"))
1288        return 27;
1289      else if (strstr (name, "[FSR]"))
1290        return 28;
1291      else if (strstr (name, "[FIR]"))
1292        return 29;
1293      else if (strstr (name, "[FDR]"))
1294        return 30;
1295      else if (strstr (name, "[CCV]"))
1296        return 32;
1297      else if (strstr (name, "[ITC]"))
1298        return 44;
1299      else if (strstr (name, "[PFS]"))
1300        return 64;
1301      else if (strstr (name, "[LC]"))
1302        return 65;
1303      else if (strstr (name, "[EC]"))
1304        return 66;
1305      abort ();
1306    case IA64_RS_CRX:
1307      if (strstr (name, "[DCR]"))
1308        return 0;
1309      else if (strstr (name, "[ITM]"))
1310        return 1;
1311      else if (strstr (name, "[IVA]"))
1312        return 2;
1313      else if (strstr (name, "[PTA]"))
1314        return 8;
1315      else if (strstr (name, "[GPTA]"))
1316        return 9;
1317      else if (strstr (name, "[IPSR]"))
1318        return 16;
1319      else if (strstr (name, "[ISR]"))
1320        return 17;
1321      else if (strstr (name, "[IIP]"))
1322        return 19;
1323      else if (strstr (name, "[IFA]"))
1324        return 20;
1325      else if (strstr (name, "[ITIR]"))
1326        return 21;
1327      else if (strstr (name, "[IIPA]"))
1328        return 22;
1329      else if (strstr (name, "[IFS]"))
1330        return 23;
1331      else if (strstr (name, "[IIM]"))
1332        return 24;
1333      else if (strstr (name, "[IHA]"))
1334        return 25;
1335      else if (strstr (name, "[LID]"))
1336        return 64;
1337      else if (strstr (name, "[IVR]"))
1338        return 65;
1339      else if (strstr (name, "[TPR]"))
1340        return 66;
1341      else if (strstr (name, "[EOI]"))
1342        return 67;
1343      else if (strstr (name, "[ITV]"))
1344        return 72;
1345      else if (strstr (name, "[PMV]"))
1346        return 73;
1347      else if (strstr (name, "[CMCV]"))
1348        return 74;
1349      abort ();
1350    case IA64_RS_PSR:
1351      if (strstr (name, ".be"))
1352        return 1;
1353      else if (strstr (name, ".up"))
1354        return 2;
1355      else if (strstr (name, ".ac"))
1356        return 3;
1357      else if (strstr (name, ".mfl"))
1358        return 4;
1359      else if (strstr (name, ".mfh"))
1360        return 5;
1361      else if (strstr (name, ".ic"))
1362        return 13;
1363      else if (strstr (name, ".i"))
1364        return 14;
1365      else if (strstr (name, ".pk"))
1366        return 15;
1367      else if (strstr (name, ".dt"))
1368        return 17;
1369      else if (strstr (name, ".dfl"))
1370        return 18;
1371      else if (strstr (name, ".dfh"))
1372        return 19;
1373      else if (strstr (name, ".sp"))
1374        return 20;
1375      else if (strstr (name, ".pp"))
1376        return 21;
1377      else if (strstr (name, ".di"))
1378        return 22;
1379      else if (strstr (name, ".si"))
1380        return 23;
1381      else if (strstr (name, ".db"))
1382        return 24;
1383      else if (strstr (name, ".lp"))
1384        return 25;
1385      else if (strstr (name, ".tb"))
1386        return 26;
1387      else if (strstr (name, ".rt"))
1388        return 27;
1389      else if (strstr (name, ".cpl"))
1390        return 32;
1391      else if (strstr (name, ".rs"))
1392        return 34;
1393      else if (strstr (name, ".mc"))
1394        return 35;
1395      else if (strstr (name, ".it"))
1396        return 36;
1397      else if (strstr (name, ".id"))
1398        return 37;
1399      else if (strstr (name, ".da"))
1400        return 38;
1401      else if (strstr (name, ".dd"))
1402        return 39;
1403      else if (strstr (name, ".ss"))
1404        return 40;
1405      else if (strstr (name, ".ri"))
1406        return 41;
1407      else if (strstr (name, ".ed"))
1408        return 43;
1409      else if (strstr (name, ".bn"))
1410        return 44;
1411      else if (strstr (name, ".ia"))
1412        return 45;
1413      else if (strstr (name, ".vm"))
1414        return 46;
1415      else
1416        abort ();
1417    default:
1418      break;
1419    }
1420  return REG_NONE;
1421}
1422
1423static int
1424lookup_specifier (const char *name)
1425{
1426  if (strchr (name, '%'))
1427    {
1428      if (strstr (name, "AR[K%]") != NULL)
1429        return IA64_RS_AR_K;
1430      if (strstr (name, "AR[UNAT]") != NULL)
1431        return IA64_RS_AR_UNAT;
1432      if (strstr (name, "AR%, % in 8") != NULL)
1433        return IA64_RS_AR;
1434      if (strstr (name, "AR%, % in 48") != NULL)
1435        return IA64_RS_ARb;
1436      if (strstr (name, "BR%") != NULL)
1437        return IA64_RS_BR;
1438      if (strstr (name, "CR[IRR%]") != NULL)
1439        return IA64_RS_CR_IRR;
1440      if (strstr (name, "CR[LRR%]") != NULL)
1441        return IA64_RS_CR_LRR;
1442      if (strstr (name, "CR%") != NULL)
1443        return IA64_RS_CR;
1444      if (strstr (name, "FR%, % in 0") != NULL)
1445        return IA64_RS_FR;
1446      if (strstr (name, "FR%, % in 2") != NULL)
1447        return IA64_RS_FRb;
1448      if (strstr (name, "GR%") != NULL)
1449        return IA64_RS_GR;
1450      if (strstr (name, "PR%, % in 1 ") != NULL)
1451        return IA64_RS_PR;
1452      if (strstr (name, "PR%, % in 16 ") != NULL)
1453	return IA64_RS_PRr;
1454
1455      warn (_("don't know how to specify %% dependency %s\n"),
1456	    name);
1457    }
1458  else if (strchr (name, '#'))
1459    {
1460      if (strstr (name, "CPUID#") != NULL)
1461        return IA64_RS_CPUID;
1462      if (strstr (name, "DBR#") != NULL)
1463        return IA64_RS_DBR;
1464      if (strstr (name, "IBR#") != NULL)
1465        return IA64_RS_IBR;
1466      if (strstr (name, "MSR#") != NULL)
1467	return IA64_RS_MSR;
1468      if (strstr (name, "PKR#") != NULL)
1469        return IA64_RS_PKR;
1470      if (strstr (name, "PMC#") != NULL)
1471        return IA64_RS_PMC;
1472      if (strstr (name, "PMD#") != NULL)
1473        return IA64_RS_PMD;
1474      if (strstr (name, "RR#") != NULL)
1475        return IA64_RS_RR;
1476
1477      warn (_("Don't know how to specify # dependency %s\n"),
1478	    name);
1479    }
1480  else if (CONST_STRNEQ (name, "AR[FPSR]"))
1481    return IA64_RS_AR_FPSR;
1482  else if (CONST_STRNEQ (name, "AR["))
1483    return IA64_RS_ARX;
1484  else if (CONST_STRNEQ (name, "CR["))
1485    return IA64_RS_CRX;
1486  else if (CONST_STRNEQ (name, "PSR."))
1487    return IA64_RS_PSR;
1488  else if (strcmp (name, "InService*") == 0)
1489    return IA64_RS_INSERVICE;
1490  else if (strcmp (name, "GR0") == 0)
1491    return IA64_RS_GR0;
1492  else if (strcmp (name, "CFM") == 0)
1493    return IA64_RS_CFM;
1494  else if (strcmp (name, "PR63") == 0)
1495    return IA64_RS_PR63;
1496  else if (strcmp (name, "RSE") == 0)
1497    return IA64_RS_RSE;
1498
1499  return IA64_RS_ANY;
1500}
1501
1502static void
1503print_dependency_table ()
1504{
1505  int i, j;
1506
1507  if (debug)
1508    {
1509      for (i=0;i < iclen;i++)
1510        {
1511          if (ics[i]->is_class)
1512            {
1513              if (!ics[i]->nsubs)
1514                {
1515                  if (ics[i]->comment)
1516		    warn (_("IC:%s [%s] has no terminals or sub-classes\n"),
1517			  ics[i]->name, ics[i]->comment);
1518		  else
1519		    warn (_("IC:%s has no terminals or sub-classes\n"),
1520			  ics[i]->name);
1521                }
1522            }
1523          else
1524            {
1525              if (!ics[i]->terminal_resolved && !ics[i]->orphan)
1526                {
1527                  if (ics[i]->comment)
1528		    warn (_("no insns mapped directly to terminal IC %s [%s]"),
1529			  ics[i]->name, ics[i]->comment);
1530		  else
1531		    warn (_("no insns mapped directly to terminal IC %s\n"),
1532			  ics[i]->name);
1533                }
1534            }
1535        }
1536
1537      for (i = 0; i < iclen; i++)
1538        {
1539          if (ics[i]->orphan)
1540            {
1541              mark_used (ics[i], 1);
1542              warn (_("class %s is defined but not used\n"),
1543		    ics[i]->name);
1544            }
1545        }
1546
1547      if (debug > 1)
1548	for (i = 0; i < rdepslen; i++)
1549	  {
1550	    static const char *mode_str[] = { "RAW", "WAW", "WAR" };
1551
1552	    if (rdeps[i]->total_chks == 0)
1553	      warn (_("Warning: rsrc %s (%s) has no chks%s\n"),
1554		    rdeps[i]->name, mode_str[rdeps[i]->mode],
1555		    rdeps[i]->total_regs ? "" : " or regs");
1556	    else if (rdeps[i]->total_regs == 0)
1557	      warn (_("rsrc %s (%s) has no regs\n"),
1558		    rdeps[i]->name, mode_str[rdeps[i]->mode]);
1559	  }
1560    }
1561
1562  /* The dependencies themselves.  */
1563  printf ("static const struct ia64_dependency\ndependencies[] = {\n");
1564  for (i = 0; i < rdepslen; i++)
1565    {
1566      /* '%', '#', AR[], CR[], or PSR. indicates we need to specify the actual
1567         resource used.  */
1568      int specifier = lookup_specifier (rdeps[i]->name);
1569      int regindex = lookup_regindex (rdeps[i]->name, specifier);
1570
1571      printf ("  { \"%s\", %d, %d, %d, %d, ",
1572              rdeps[i]->name, specifier,
1573              (int)rdeps[i]->mode, (int)rdeps[i]->semantics, regindex);
1574      if (rdeps[i]->semantics == IA64_DVS_OTHER)
1575	{
1576	  const char *quote, *rest;
1577
1578	  putchar ('\"');
1579	  rest = rdeps[i]->extra;
1580	  quote = strchr (rest, '\"');
1581	  while (quote != NULL)
1582	    {
1583	      printf ("%.*s\\\"", (int) (quote - rest), rest);
1584	      rest = quote + 1;
1585	      quote = strchr (rest, '\"');
1586	    }
1587	  printf ("%s\", ", rest);
1588	}
1589      else
1590	printf ("NULL, ");
1591      printf("},\n");
1592    }
1593  printf ("};\n\n");
1594
1595  /* And dependency lists.  */
1596  for (i=0;i < dlistlen;i++)
1597    {
1598      int len = 2;
1599      printf ("static const unsigned short dep%d[] = {\n  ", i);
1600      for (j=0;j < dlists[i]->len; j++)
1601        {
1602          len += printf ("%d, ", dlists[i]->deps[j]);
1603          if (len > 75)
1604            {
1605              printf("\n  ");
1606              len = 2;
1607            }
1608        }
1609      printf ("\n};\n\n");
1610    }
1611
1612  /* And opcode dependency list.  */
1613  printf ("#define NELS(X) (sizeof(X)/sizeof(X[0]))\n");
1614  printf ("static const struct ia64_opcode_dependency\n");
1615  printf ("op_dependencies[] = {\n");
1616  for (i = 0; i < opdeplen; i++)
1617    {
1618      printf ("  { ");
1619      if (opdeps[i]->chk == -1)
1620        printf ("0, NULL, ");
1621      else
1622        printf ("NELS(dep%d), dep%d, ", opdeps[i]->chk, opdeps[i]->chk);
1623      if (opdeps[i]->reg == -1)
1624        printf ("0, NULL, ");
1625      else
1626        printf ("NELS(dep%d), dep%d, ", opdeps[i]->reg, opdeps[i]->reg);
1627      printf ("},\n");
1628    }
1629  printf ("};\n\n");
1630}
1631
1632
1633/* Add STR to the string table.  */
1634static struct string_entry *
1635insert_string (char *str)
1636{
1637  int start = 0, end = strtablen;
1638  int i, x;
1639
1640  if (strtablen == strtabtotlen)
1641    {
1642      strtabtotlen += 20;
1643      string_table = (struct string_entry **)
1644	xrealloc (string_table,
1645		  sizeof (struct string_entry **) * strtabtotlen);
1646    }
1647
1648  if (strtablen == 0)
1649    {
1650      strtablen = 1;
1651      string_table[0] = tmalloc (struct string_entry);
1652      string_table[0]->s = xstrdup (str);
1653      string_table[0]->num = 0;
1654      return string_table[0];
1655    }
1656
1657  if (strcmp (str, string_table[strtablen - 1]->s) > 0)
1658    i = end;
1659  else if (strcmp (str, string_table[0]->s) < 0)
1660    i = 0;
1661  else
1662    {
1663      while (1)
1664	{
1665	  int c;
1666
1667	  i = (start + end) / 2;
1668	  c = strcmp (str, string_table[i]->s);
1669
1670	  if (c < 0)
1671	    end = i - 1;
1672	  else if (c == 0)
1673	    return string_table[i];
1674	  else
1675	    start = i + 1;
1676
1677	  if (start > end)
1678	    break;
1679	}
1680    }
1681
1682  for (; i > 0 && i < strtablen; i--)
1683    if (strcmp (str, string_table[i - 1]->s) > 0)
1684      break;
1685
1686  for (; i < strtablen; i++)
1687    if (strcmp (str, string_table[i]->s) < 0)
1688      break;
1689
1690  for (x = strtablen - 1; x >= i; x--)
1691    {
1692      string_table[x + 1] = string_table[x];
1693      string_table[x + 1]->num = x + 1;
1694    }
1695
1696  string_table[i] = tmalloc (struct string_entry);
1697  string_table[i]->s = xstrdup (str);
1698  string_table[i]->num = i;
1699  strtablen++;
1700
1701  return string_table[i];
1702}
1703
1704static struct bittree *
1705make_bittree_entry (void)
1706{
1707  struct bittree *res = tmalloc (struct bittree);
1708
1709  res->disent = NULL;
1710  res->bits[0] = NULL;
1711  res->bits[1] = NULL;
1712  res->bits[2] = NULL;
1713  res->skip_flag = 0;
1714  res->bits_to_skip = 0;
1715  return res;
1716}
1717
1718
1719static struct disent *
1720add_dis_table_ent (which, insn, order, completer_index)
1721     struct disent *which;
1722     int insn;
1723     int order;
1724     int completer_index;
1725{
1726  int ci = 0;
1727  struct disent *ent;
1728
1729  if (which != NULL)
1730    {
1731      ent = which;
1732
1733      ent->nextcnt++;
1734      while (ent->nexte != NULL)
1735	ent = ent->nexte;
1736
1737      ent = (ent->nexte = tmalloc (struct disent));
1738    }
1739  else
1740    {
1741      ent = tmalloc (struct disent);
1742      ent->next_ent = disinsntable;
1743      disinsntable = ent;
1744      which = ent;
1745    }
1746  ent->nextcnt = 0;
1747  ent->nexte = NULL;
1748  ent->insn = insn;
1749  ent->priority = order;
1750
1751  while (completer_index != 1)
1752    {
1753      ci = (ci << 1) | (completer_index & 1);
1754      completer_index >>= 1;
1755    }
1756  ent->completer_index = ci;
1757  return which;
1758}
1759
1760static void
1761finish_distable ()
1762{
1763  struct disent *ent = disinsntable;
1764  struct disent *prev = ent;
1765
1766  ent->ournum = 32768;
1767  while ((ent = ent->next_ent) != NULL)
1768    {
1769      ent->ournum = prev->ournum + prev->nextcnt + 1;
1770      prev = ent;
1771    }
1772}
1773
1774static void
1775insert_bit_table_ent (curr_ent, bit, opcode, mask,
1776                      opcodenum, order, completer_index)
1777     struct bittree *curr_ent;
1778     int bit;
1779     ia64_insn opcode;
1780     ia64_insn mask;
1781     int opcodenum;
1782     int order;
1783     int completer_index;
1784{
1785  ia64_insn m;
1786  int b;
1787  struct bittree *next;
1788
1789  if (bit == -1)
1790    {
1791      struct disent *nent = add_dis_table_ent (curr_ent->disent,
1792                                               opcodenum, order,
1793					       completer_index);
1794      curr_ent->disent = nent;
1795      return;
1796    }
1797
1798  m = ((ia64_insn) 1) << bit;
1799
1800  if (mask & m)
1801    b = (opcode & m) ? 1 : 0;
1802  else
1803    b = 2;
1804
1805  next = curr_ent->bits[b];
1806  if (next == NULL)
1807    {
1808      next = make_bittree_entry ();
1809      curr_ent->bits[b] = next;
1810    }
1811  insert_bit_table_ent (next, bit - 1, opcode, mask, opcodenum, order,
1812			completer_index);
1813}
1814
1815static void
1816add_dis_entry (first, opcode, mask, opcodenum, ent, completer_index)
1817     struct bittree *first;
1818     ia64_insn opcode;
1819     ia64_insn mask;
1820     int opcodenum;
1821     struct completer_entry *ent;
1822     int completer_index;
1823{
1824  if (completer_index & (1 << 20))
1825    abort ();
1826
1827  while (ent != NULL)
1828    {
1829      ia64_insn newopcode = (opcode & (~ ent->mask)) | ent->bits;
1830      add_dis_entry (first, newopcode, mask, opcodenum, ent->addl_entries,
1831		     (completer_index << 1) | 1);
1832
1833      if (ent->is_terminal)
1834	{
1835	  insert_bit_table_ent (bittree, 40, newopcode, mask,
1836                                opcodenum, opcode_count - ent->order - 1,
1837				(completer_index << 1) | 1);
1838	}
1839      completer_index <<= 1;
1840      ent = ent->alternative;
1841    }
1842}
1843
1844/* This optimization pass combines multiple "don't care" nodes.  */
1845static void
1846compact_distree (ent)
1847     struct bittree *ent;
1848{
1849#define IS_SKIP(ent) \
1850    ((ent->bits[2] !=NULL) \
1851     && (ent->bits[0] == NULL && ent->bits[1] == NULL && ent->skip_flag == 0))
1852
1853  int bitcnt = 0;
1854  struct bittree *nent = ent;
1855  int x;
1856
1857  while (IS_SKIP (nent))
1858    {
1859      bitcnt++;
1860      nent = nent->bits[2];
1861    }
1862
1863  if (bitcnt)
1864    {
1865      struct bittree *next = ent->bits[2];
1866
1867      ent->bits[0] = nent->bits[0];
1868      ent->bits[1] = nent->bits[1];
1869      ent->bits[2] = nent->bits[2];
1870      ent->disent = nent->disent;
1871      ent->skip_flag = 1;
1872      ent->bits_to_skip = bitcnt;
1873      while (next != nent)
1874	{
1875	  struct bittree *b = next;
1876	  next = next->bits[2];
1877	  free (b);
1878	}
1879      free (nent);
1880    }
1881
1882  for (x = 0; x < 3; x++)
1883    {
1884      struct bittree *i = ent->bits[x];
1885
1886      if (i != NULL)
1887	compact_distree (i);
1888    }
1889}
1890
1891static unsigned char *insn_list;
1892static int insn_list_len = 0;
1893static int tot_insn_list_len = 0;
1894
1895/* Generate the disassembler state machine corresponding to the tree
1896   in ENT.  */
1897static void
1898gen_dis_table (ent)
1899     struct bittree *ent;
1900{
1901  int x;
1902  int our_offset = insn_list_len;
1903  int bitsused = 5;
1904  int totbits = bitsused;
1905  int needed_bytes;
1906  int zero_count = 0;
1907  int zero_dest = 0;	/* Initialize this with 0 to keep gcc quiet...  */
1908
1909  /* If this is a terminal entry, there's no point in skipping any
1910     bits.  */
1911  if (ent->skip_flag && ent->bits[0] == NULL && ent->bits[1] == NULL &&
1912      ent->bits[2] == NULL)
1913    {
1914      if (ent->disent == NULL)
1915	abort ();
1916      else
1917	ent->skip_flag = 0;
1918    }
1919
1920  /* Calculate the amount of space needed for this entry, or at least
1921     a conservatively large approximation.  */
1922  if (ent->skip_flag)
1923    totbits += 5;
1924
1925  for (x = 1; x < 3; x++)
1926    if (ent->bits[x] != NULL)
1927      totbits += 16;
1928
1929  if (ent->disent != NULL)
1930    {
1931      if (ent->bits[2] != NULL)
1932	abort ();
1933
1934      totbits += 16;
1935    }
1936
1937  /* Now allocate the space.  */
1938  needed_bytes = (totbits + 7) / 8;
1939  if ((needed_bytes + insn_list_len) > tot_insn_list_len)
1940    {
1941      tot_insn_list_len += 256;
1942      insn_list = (unsigned char *) xrealloc (insn_list, tot_insn_list_len);
1943    }
1944  our_offset = insn_list_len;
1945  insn_list_len += needed_bytes;
1946  memset (insn_list + our_offset, 0, needed_bytes);
1947
1948  /* Encode the skip entry by setting bit 6 set in the state op field,
1949     and store the # of bits to skip immediately after.  */
1950  if (ent->skip_flag)
1951    {
1952      bitsused += 5;
1953      insn_list[our_offset + 0] |= 0x40 | ((ent->bits_to_skip >> 2) & 0xf);
1954      insn_list[our_offset + 1] |= ((ent->bits_to_skip & 3) << 6);
1955    }
1956
1957#define IS_ONLY_IFZERO(ENT) \
1958  ((ENT)->bits[0] != NULL && (ENT)->bits[1] == NULL && (ENT)->bits[2] == NULL \
1959   && (ENT)->disent == NULL && (ENT)->skip_flag == 0)
1960
1961  /* Store an "if (bit is zero)" instruction by setting bit 7 in the
1962     state op field.  */
1963  if (ent->bits[0] != NULL)
1964    {
1965      struct bittree *nent = ent->bits[0];
1966      zero_count = 0;
1967
1968      insn_list[our_offset] |= 0x80;
1969
1970      /* We can encode sequences of multiple "if (bit is zero)" tests
1971	 by storing the # of zero bits to check in the lower 3 bits of
1972	 the instruction.  However, this only applies if the state
1973	 solely tests for a zero bit.  */
1974
1975      if (IS_ONLY_IFZERO (ent))
1976	{
1977	  while (IS_ONLY_IFZERO (nent) && zero_count < 7)
1978	    {
1979	      nent = nent->bits[0];
1980	      zero_count++;
1981	    }
1982
1983	  insn_list[our_offset + 0] |= zero_count;
1984	}
1985      zero_dest = insn_list_len;
1986      gen_dis_table (nent);
1987    }
1988
1989  /* Now store the remaining tests.  We also handle a sole "termination
1990     entry" by storing it as an "any bit" test.  */
1991
1992  for (x = 1; x < 3; x++)
1993    {
1994      if (ent->bits[x] != NULL || (x == 2 && ent->disent != NULL))
1995	{
1996	  struct bittree *i = ent->bits[x];
1997	  int idest;
1998	  int currbits = 15;
1999
2000	  if (i != NULL)
2001	    {
2002	      /* If the instruction being branched to only consists of
2003		 a termination entry, use the termination entry as the
2004		 place to branch to instead.  */
2005	      if (i->bits[0] == NULL && i->bits[1] == NULL
2006		  && i->bits[2] == NULL && i->disent != NULL)
2007		{
2008		  idest = i->disent->ournum;
2009		  i = NULL;
2010		}
2011	      else
2012		idest = insn_list_len - our_offset;
2013	    }
2014	  else
2015	    idest = ent->disent->ournum;
2016
2017	  /* If the destination offset for the if (bit is 1) test is less
2018	     than 256 bytes away, we can store it as 8-bits instead of 16;
2019	     the instruction has bit 5 set for the 16-bit address, and bit
2020	     4 for the 8-bit address.  Since we've already allocated 16
2021	     bits for the address we need to deallocate the space.
2022
2023	     Note that branchings within the table are relative, and
2024	     there are no branches that branch past our instruction yet
2025	     so we do not need to adjust any other offsets.  */
2026	  if (x == 1)
2027	    {
2028	      if (idest <= 256)
2029		{
2030		  int start = our_offset + bitsused / 8 + 1;
2031
2032		  memmove (insn_list + start,
2033			   insn_list + start + 1,
2034			   insn_list_len - (start + 1));
2035		  currbits = 7;
2036		  totbits -= 8;
2037		  needed_bytes--;
2038		  insn_list_len--;
2039		  insn_list[our_offset] |= 0x10;
2040		  idest--;
2041		}
2042	      else
2043		insn_list[our_offset] |= 0x20;
2044	    }
2045	  else
2046	    {
2047	      /* An instruction which solely consists of a termination
2048		 marker and whose disassembly name index is < 4096
2049		 can be stored in 16 bits.  The encoding is slightly
2050		 odd; the upper 4 bits of the instruction are 0x3, and
2051		 bit 3 loses its normal meaning.  */
2052
2053	      if (ent->bits[0] == NULL && ent->bits[1] == NULL
2054		  && ent->bits[2] == NULL && ent->skip_flag == 0
2055		  && ent->disent != NULL
2056		  && ent->disent->ournum < (32768 + 4096))
2057		{
2058		  int start = our_offset + bitsused / 8 + 1;
2059
2060		  memmove (insn_list + start,
2061			   insn_list + start + 1,
2062			   insn_list_len - (start + 1));
2063		  currbits = 11;
2064		  totbits -= 5;
2065		  bitsused--;
2066		  needed_bytes--;
2067		  insn_list_len--;
2068		  insn_list[our_offset] |= 0x30;
2069		  idest &= ~32768;
2070		}
2071	      else
2072		insn_list[our_offset] |= 0x08;
2073	    }
2074
2075	  if (debug)
2076	    {
2077	      int id = idest;
2078
2079	      if (i == NULL)
2080		id |= 32768;
2081	      else if (! (id & 32768))
2082		id += our_offset;
2083
2084	      if (x == 1)
2085		printf ("%d: if (1) goto %d\n", our_offset, id);
2086	      else
2087		printf ("%d: try %d\n", our_offset, id);
2088	    }
2089
2090	  /* Store the address of the entry being branched to.  */
2091	  while (currbits >= 0)
2092	    {
2093	      unsigned char *byte = insn_list + our_offset + bitsused / 8;
2094
2095	      if (idest & (1 << currbits))
2096		*byte |= (1 << (7 - (bitsused % 8)));
2097
2098	      bitsused++;
2099	      currbits--;
2100	    }
2101
2102	  /* Now generate the states for the entry being branched to.  */
2103	  if (i != NULL)
2104	    gen_dis_table (i);
2105	}
2106    }
2107
2108  if (debug)
2109    {
2110      if (ent->skip_flag)
2111	printf ("%d: skipping %d\n", our_offset, ent->bits_to_skip);
2112
2113      if (ent->bits[0] != NULL)
2114	printf ("%d: if (0:%d) goto %d\n", our_offset, zero_count + 1,
2115		zero_dest);
2116    }
2117
2118  if (bitsused != totbits)
2119    abort ();
2120}
2121
2122static void
2123print_dis_table (void)
2124{
2125  int x;
2126  struct disent *cent = disinsntable;
2127
2128  printf ("static const char dis_table[] = {\n");
2129  for (x = 0; x < insn_list_len; x++)
2130    {
2131      if ((x > 0) && ((x % 12) == 0))
2132	printf ("\n");
2133
2134      printf ("0x%02x, ", insn_list[x]);
2135    }
2136  printf ("\n};\n\n");
2137
2138  printf ("static const struct ia64_dis_names ia64_dis_names[] = {\n");
2139  while (cent != NULL)
2140    {
2141      struct disent *ent = cent;
2142
2143      while (ent != NULL)
2144	{
2145	  printf ("{ 0x%x, %d, %d, %d },\n", ent->completer_index,
2146		  ent->insn, (ent->nexte != NULL ? 1 : 0),
2147                  ent->priority);
2148	  ent = ent->nexte;
2149	}
2150      cent = cent->next_ent;
2151    }
2152  printf ("};\n\n");
2153}
2154
2155static void
2156generate_disassembler (void)
2157{
2158  int i;
2159
2160  bittree = make_bittree_entry ();
2161
2162  for (i = 0; i < otlen; i++)
2163    {
2164      struct main_entry *ptr = ordered_table[i];
2165
2166      if (ptr->opcode->type != IA64_TYPE_DYN)
2167	add_dis_entry (bittree,
2168		       ptr->opcode->opcode, ptr->opcode->mask,
2169		       ptr->main_index,
2170		       ptr->completers, 1);
2171    }
2172
2173  compact_distree (bittree);
2174  finish_distable ();
2175  gen_dis_table (bittree);
2176
2177  print_dis_table ();
2178}
2179
2180static void
2181print_string_table (void)
2182{
2183  int x;
2184  char lbuf[80], buf[80];
2185  int blen = 0;
2186
2187  printf ("static const char * const ia64_strings[] = {\n");
2188  lbuf[0] = '\0';
2189
2190  for (x = 0; x < strtablen; x++)
2191    {
2192      int len;
2193
2194      if (strlen (string_table[x]->s) > 75)
2195	abort ();
2196
2197      sprintf (buf, " \"%s\",", string_table[x]->s);
2198      len = strlen (buf);
2199
2200      if ((blen + len) > 75)
2201	{
2202	  printf (" %s\n", lbuf);
2203	  lbuf[0] = '\0';
2204	  blen = 0;
2205	}
2206      strcat (lbuf, buf);
2207      blen += len;
2208    }
2209
2210  if (blen > 0)
2211    printf (" %s\n", lbuf);
2212
2213  printf ("};\n\n");
2214}
2215
2216static struct completer_entry **glist;
2217static int glistlen = 0;
2218static int glisttotlen = 0;
2219
2220/* If the completer trees ENT1 and ENT2 are equal, return 1.  */
2221
2222static int
2223completer_entries_eq (ent1, ent2)
2224     struct completer_entry *ent1, *ent2;
2225{
2226  while (ent1 != NULL && ent2 != NULL)
2227    {
2228      if (ent1->name->num != ent2->name->num
2229	  || ent1->bits != ent2->bits
2230	  || ent1->mask != ent2->mask
2231	  || ent1->is_terminal != ent2->is_terminal
2232          || ent1->dependencies != ent2->dependencies
2233          || ent1->order != ent2->order)
2234	return 0;
2235
2236      if (! completer_entries_eq (ent1->addl_entries, ent2->addl_entries))
2237	return 0;
2238
2239      ent1 = ent1->alternative;
2240      ent2 = ent2->alternative;
2241    }
2242
2243  return ent1 == ent2;
2244}
2245
2246/* Insert ENT into the global list of completers and return it.  If an
2247   equivalent entry (according to completer_entries_eq) already exists,
2248   it is returned instead.  */
2249static struct completer_entry *
2250insert_gclist (struct completer_entry *ent)
2251{
2252  if (ent != NULL)
2253    {
2254      int i;
2255      int x;
2256      int start = 0, end;
2257
2258      ent->addl_entries = insert_gclist (ent->addl_entries);
2259      ent->alternative = insert_gclist (ent->alternative);
2260
2261      i = glistlen / 2;
2262      end = glistlen;
2263
2264      if (glisttotlen == glistlen)
2265	{
2266	  glisttotlen += 20;
2267	  glist = (struct completer_entry **)
2268	    xrealloc (glist, sizeof (struct completer_entry *) * glisttotlen);
2269	}
2270
2271      if (glistlen == 0)
2272	{
2273	  glist[0] = ent;
2274	  glistlen = 1;
2275	  return ent;
2276	}
2277
2278      if (ent->name->num < glist[0]->name->num)
2279	i = 0;
2280      else if (ent->name->num > glist[end - 1]->name->num)
2281	i = end;
2282      else
2283	{
2284	  int c;
2285
2286	  while (1)
2287	    {
2288	      i = (start + end) / 2;
2289	      c = ent->name->num - glist[i]->name->num;
2290
2291	      if (c < 0)
2292		end = i - 1;
2293	      else if (c == 0)
2294		{
2295		  while (i > 0
2296			 && ent->name->num == glist[i - 1]->name->num)
2297		    i--;
2298
2299		  break;
2300		}
2301	      else
2302		start = i + 1;
2303
2304	      if (start > end)
2305		break;
2306	    }
2307
2308	  if (c == 0)
2309	    {
2310	      while (i < glistlen)
2311		{
2312		  if (ent->name->num != glist[i]->name->num)
2313		    break;
2314
2315		  if (completer_entries_eq (ent, glist[i]))
2316		    return glist[i];
2317
2318		  i++;
2319		}
2320	    }
2321	}
2322
2323      for (; i > 0 && i < glistlen; i--)
2324	if (ent->name->num >= glist[i - 1]->name->num)
2325	  break;
2326
2327      for (; i < glistlen; i++)
2328	if (ent->name->num < glist[i]->name->num)
2329	  break;
2330
2331      for (x = glistlen - 1; x >= i; x--)
2332	glist[x + 1] = glist[x];
2333
2334      glist[i] = ent;
2335      glistlen++;
2336    }
2337  return ent;
2338}
2339
2340static int
2341get_prefix_len (name)
2342     const char *name;
2343{
2344  char *c;
2345
2346  if (name[0] == '\0')
2347    return 0;
2348
2349  c = strchr (name, '.');
2350  if (c != NULL)
2351    return c - name;
2352  else
2353    return strlen (name);
2354}
2355
2356static void
2357compute_completer_bits (ment, ent)
2358     struct main_entry *ment;
2359     struct completer_entry *ent;
2360{
2361  while (ent != NULL)
2362    {
2363      compute_completer_bits (ment, ent->addl_entries);
2364
2365      if (ent->is_terminal)
2366	{
2367	  ia64_insn mask = 0;
2368	  ia64_insn our_bits = ent->bits;
2369	  struct completer_entry *p = ent->parent;
2370	  ia64_insn p_bits;
2371	  int x;
2372
2373	  while (p != NULL && ! p->is_terminal)
2374	    p = p->parent;
2375
2376	  if (p != NULL)
2377	    p_bits = p->bits;
2378	  else
2379	    p_bits = ment->opcode->opcode;
2380
2381	  for (x = 0; x < 64; x++)
2382	    {
2383	      ia64_insn m = ((ia64_insn) 1) << x;
2384
2385	      if ((p_bits & m) != (our_bits & m))
2386		mask |= m;
2387	      else
2388		our_bits &= ~m;
2389	    }
2390	  ent->bits = our_bits;
2391	  ent->mask = mask;
2392	}
2393      else
2394	{
2395	  ent->bits = 0;
2396	  ent->mask = 0;
2397	}
2398
2399      ent = ent->alternative;
2400    }
2401}
2402
2403/* Find identical completer trees that are used in different
2404   instructions and collapse their entries.  */
2405static void
2406collapse_redundant_completers (void)
2407{
2408  struct main_entry *ptr;
2409  int x;
2410
2411  for (ptr = maintable; ptr != NULL; ptr = ptr->next)
2412    {
2413      if (ptr->completers == NULL)
2414	abort ();
2415
2416      compute_completer_bits (ptr, ptr->completers);
2417      ptr->completers = insert_gclist (ptr->completers);
2418    }
2419
2420  /* The table has been finalized, now number the indexes.  */
2421  for (x = 0; x < glistlen; x++)
2422    glist[x]->num = x;
2423}
2424
2425
2426/* Attach two lists of dependencies to each opcode.
2427   1) all resources which, when already marked in use, conflict with this
2428   opcode (chks)
2429   2) all resources which must be marked in use when this opcode is used
2430   (regs).  */
2431static int
2432insert_opcode_dependencies (opc, cmp)
2433     struct ia64_opcode *opc;
2434     struct completer_entry *cmp ATTRIBUTE_UNUSED;
2435{
2436  /* Note all resources which point to this opcode.  rfi has the most chks
2437     (79) and cmpxchng has the most regs (54) so 100 here should be enough.  */
2438  int i;
2439  int nregs = 0;
2440  unsigned short regs[256];
2441  int nchks = 0;
2442  unsigned short chks[256];
2443  /* Flag insns for which no class matched; there should be none.  */
2444  int no_class_found = 1;
2445
2446  for (i = 0; i < rdepslen; i++)
2447    {
2448      struct rdep *rs = rdeps[i];
2449      int j;
2450
2451      if (strcmp (opc->name, "cmp.eq.and") == 0
2452          && CONST_STRNEQ (rs->name, "PR%")
2453          && rs->mode == 1)
2454        no_class_found = 99;
2455
2456      for (j=0; j < rs->nregs;j++)
2457        {
2458          int ic_note = 0;
2459
2460          if (in_iclass (opc, ics[rs->regs[j]], NULL, NULL, &ic_note))
2461            {
2462              /* We can ignore ic_note 11 for non PR resources.  */
2463              if (ic_note == 11 && ! CONST_STRNEQ (rs->name, "PR"))
2464                ic_note = 0;
2465
2466              if (ic_note != 0 && rs->regnotes[j] != 0
2467                  && ic_note != rs->regnotes[j]
2468                  && !(ic_note == 11 && rs->regnotes[j] == 1))
2469                warn (_("IC note %d in opcode %s (IC:%s) conflicts with resource %s note %d\n"),
2470		      ic_note, opc->name, ics[rs->regs[j]]->name,
2471		      rs->name, rs->regnotes[j]);
2472              /* Instruction class notes override resource notes.
2473                 So far, only note 11 applies to an IC instead of a resource,
2474                 and note 11 implies note 1.  */
2475              if (ic_note)
2476                regs[nregs++] = RDEP(ic_note, i);
2477              else
2478                regs[nregs++] = RDEP(rs->regnotes[j], i);
2479              no_class_found = 0;
2480              ++rs->total_regs;
2481            }
2482        }
2483
2484      for (j = 0; j < rs->nchks; j++)
2485        {
2486          int ic_note = 0;
2487
2488          if (in_iclass (opc, ics[rs->chks[j]], NULL, NULL, &ic_note))
2489            {
2490              /* We can ignore ic_note 11 for non PR resources.  */
2491              if (ic_note == 11 && ! CONST_STRNEQ (rs->name, "PR"))
2492                ic_note = 0;
2493
2494              if (ic_note != 0 && rs->chknotes[j] != 0
2495                  && ic_note != rs->chknotes[j]
2496                  && !(ic_note == 11 && rs->chknotes[j] == 1))
2497                warn (_("IC note %d for opcode %s (IC:%s) conflicts with resource %s note %d\n"),
2498		      ic_note, opc->name, ics[rs->chks[j]]->name,
2499		      rs->name, rs->chknotes[j]);
2500              if (ic_note)
2501                chks[nchks++] = RDEP(ic_note, i);
2502              else
2503                chks[nchks++] = RDEP(rs->chknotes[j], i);
2504              no_class_found = 0;
2505              ++rs->total_chks;
2506            }
2507        }
2508    }
2509
2510  if (no_class_found)
2511    warn (_("opcode %s has no class (ops %d %d %d)\n"),
2512	  opc->name,
2513	  opc->operands[0], opc->operands[1], opc->operands[2]);
2514
2515  return insert_dependencies (nchks, chks, nregs, regs);
2516}
2517
2518static void
2519insert_completer_entry (opc, tabent, order)
2520     struct ia64_opcode *opc;
2521     struct main_entry *tabent;
2522     int order;
2523{
2524  struct completer_entry **ptr = &tabent->completers;
2525  struct completer_entry *parent = NULL;
2526  char pcopy[129], *prefix;
2527  int at_end = 0;
2528
2529  if (strlen (opc->name) > 128)
2530    abort ();
2531
2532  strcpy (pcopy, opc->name);
2533  prefix = pcopy + get_prefix_len (pcopy);
2534
2535  if (prefix[0] != '\0')
2536    prefix++;
2537
2538  while (! at_end)
2539    {
2540      int need_new_ent = 1;
2541      int plen = get_prefix_len (prefix);
2542      struct string_entry *sent;
2543
2544      at_end = (prefix[plen] == '\0');
2545      prefix[plen] = '\0';
2546      sent = insert_string (prefix);
2547
2548      while (*ptr != NULL)
2549	{
2550	  int cmpres = sent->num - (*ptr)->name->num;
2551
2552	  if (cmpres == 0)
2553	    {
2554	      need_new_ent = 0;
2555	      break;
2556	    }
2557	  else
2558	    ptr = &((*ptr)->alternative);
2559	}
2560
2561      if (need_new_ent)
2562	{
2563	  struct completer_entry *nent = tmalloc (struct completer_entry);
2564
2565	  nent->name = sent;
2566	  nent->parent = parent;
2567	  nent->addl_entries = NULL;
2568	  nent->alternative = *ptr;
2569	  *ptr = nent;
2570	  nent->is_terminal = 0;
2571          nent->dependencies = -1;
2572	}
2573
2574      if (! at_end)
2575	{
2576	  parent = *ptr;
2577	  ptr = &((*ptr)->addl_entries);
2578	  prefix += plen + 1;
2579	}
2580    }
2581
2582  if ((*ptr)->is_terminal)
2583    abort ();
2584
2585  (*ptr)->is_terminal = 1;
2586  (*ptr)->mask = (ia64_insn)-1;
2587  (*ptr)->bits = opc->opcode;
2588  (*ptr)->dependencies = insert_opcode_dependencies (opc, *ptr);
2589  (*ptr)->order = order;
2590}
2591
2592static void
2593print_completer_entry (ent)
2594     struct completer_entry *ent;
2595{
2596  int moffset = 0;
2597  ia64_insn mask = ent->mask, bits = ent->bits;
2598
2599  if (mask != 0)
2600    {
2601      while (! (mask & 1))
2602	{
2603	  moffset++;
2604	  mask = mask >> 1;
2605	  bits = bits >> 1;
2606	}
2607
2608      if (bits & 0xffffffff00000000LL)
2609	abort ();
2610    }
2611
2612  printf ("  { 0x%x, 0x%x, %d, %d, %d, %d, %d, %d },\n",
2613	  (int)bits,
2614	  (int)mask,
2615	  ent->name->num,
2616	  ent->alternative != NULL ? ent->alternative->num : -1,
2617	  ent->addl_entries != NULL ? ent->addl_entries->num : -1,
2618	  moffset,
2619	  ent->is_terminal ? 1 : 0,
2620          ent->dependencies);
2621}
2622
2623static void
2624print_completer_table ()
2625{
2626  int x;
2627
2628  printf ("static const struct ia64_completer_table\ncompleter_table[] = {\n");
2629  for (x = 0; x < glistlen; x++)
2630    print_completer_entry (glist[x]);
2631  printf ("};\n\n");
2632}
2633
2634static int
2635opcodes_eq (opc1, opc2)
2636     struct ia64_opcode *opc1;
2637     struct ia64_opcode *opc2;
2638{
2639  int x;
2640  int plen1, plen2;
2641
2642  if ((opc1->mask != opc2->mask) || (opc1->type != opc2->type)
2643      || (opc1->num_outputs != opc2->num_outputs)
2644      || (opc1->flags != opc2->flags))
2645    return 0;
2646
2647  for (x = 0; x < 5; x++)
2648    if (opc1->operands[x] != opc2->operands[x])
2649      return 0;
2650
2651  plen1 = get_prefix_len (opc1->name);
2652  plen2 = get_prefix_len (opc2->name);
2653
2654  if (plen1 == plen2 && (memcmp (opc1->name, opc2->name, plen1) == 0))
2655    return 1;
2656
2657  return 0;
2658}
2659
2660static void
2661add_opcode_entry (opc)
2662     struct ia64_opcode *opc;
2663{
2664  struct main_entry **place;
2665  struct string_entry *name;
2666  char prefix[129];
2667  int found_it = 0;
2668
2669  if (strlen (opc->name) > 128)
2670    abort ();
2671
2672  place = &maintable;
2673  strcpy (prefix, opc->name);
2674  prefix[get_prefix_len (prefix)] = '\0';
2675  name = insert_string (prefix);
2676
2677  /* Walk the list of opcode table entries.  If it's a new
2678     instruction, allocate and fill in a new entry.  Note
2679     the main table is alphabetical by opcode name.  */
2680
2681  while (*place != NULL)
2682    {
2683      if ((*place)->name->num == name->num
2684	  && opcodes_eq ((*place)->opcode, opc))
2685	{
2686	  found_it = 1;
2687	  break;
2688	}
2689      if ((*place)->name->num > name->num)
2690	break;
2691
2692      place = &((*place)->next);
2693    }
2694  if (! found_it)
2695    {
2696      struct main_entry *nent = tmalloc (struct main_entry);
2697
2698      nent->name = name;
2699      nent->opcode = opc;
2700      nent->next = *place;
2701      nent->completers = 0;
2702      *place = nent;
2703
2704      if (otlen == ottotlen)
2705        {
2706          ottotlen += 20;
2707          ordered_table = (struct main_entry **)
2708            xrealloc (ordered_table, sizeof (struct main_entry *) * ottotlen);
2709        }
2710      ordered_table[otlen++] = nent;
2711    }
2712
2713  insert_completer_entry (opc, *place, opcode_count++);
2714}
2715
2716static void
2717print_main_table (void)
2718{
2719  struct main_entry *ptr = maintable;
2720  int index = 0;
2721
2722  printf ("static const struct ia64_main_table\nmain_table[] = {\n");
2723  while (ptr != NULL)
2724    {
2725      printf ("  { %d, %d, %d, 0x",
2726	      ptr->name->num,
2727	      ptr->opcode->type,
2728	      ptr->opcode->num_outputs);
2729      opcode_fprintf_vma (stdout, ptr->opcode->opcode);
2730      printf ("ull, 0x");
2731      opcode_fprintf_vma (stdout, ptr->opcode->mask);
2732      printf ("ull, { %d, %d, %d, %d, %d }, 0x%x, %d, },\n",
2733	      ptr->opcode->operands[0],
2734	      ptr->opcode->operands[1],
2735	      ptr->opcode->operands[2],
2736	      ptr->opcode->operands[3],
2737	      ptr->opcode->operands[4],
2738	      ptr->opcode->flags,
2739	      ptr->completers->num);
2740
2741      ptr->main_index = index++;
2742
2743      ptr = ptr->next;
2744    }
2745  printf ("};\n\n");
2746}
2747
2748static void
2749shrink (table)
2750     struct ia64_opcode *table;
2751{
2752  int curr_opcode;
2753
2754  for (curr_opcode = 0; table[curr_opcode].name != NULL; curr_opcode++)
2755    {
2756      add_opcode_entry (table + curr_opcode);
2757      if (table[curr_opcode].num_outputs == 2
2758	  && ((table[curr_opcode].operands[0] == IA64_OPND_P1
2759	       && table[curr_opcode].operands[1] == IA64_OPND_P2)
2760	      || (table[curr_opcode].operands[0] == IA64_OPND_P2
2761		  && table[curr_opcode].operands[1] == IA64_OPND_P1)))
2762	{
2763	  struct ia64_opcode *alias = tmalloc(struct ia64_opcode);
2764	  unsigned i;
2765
2766	  *alias = table[curr_opcode];
2767	  for (i = 2; i < NELEMS (alias->operands); ++i)
2768	    alias->operands[i - 1] = alias->operands[i];
2769	  alias->operands[NELEMS (alias->operands) - 1] = IA64_OPND_NIL;
2770	  --alias->num_outputs;
2771	  alias->flags |= PSEUDO;
2772	  add_opcode_entry (alias);
2773	}
2774    }
2775}
2776
2777
2778/* Program options.  */
2779#define OPTION_SRCDIR	200
2780
2781struct option long_options[] =
2782{
2783  {"srcdir",  required_argument, NULL, OPTION_SRCDIR},
2784  {"debug",   no_argument,       NULL, 'd'},
2785  {"version", no_argument,       NULL, 'V'},
2786  {"help",    no_argument,       NULL, 'h'},
2787  {0,         no_argument,       NULL, 0}
2788};
2789
2790static void
2791print_version (void)
2792{
2793  printf ("%s: version 1.0\n", program_name);
2794  xexit (0);
2795}
2796
2797static void
2798usage (FILE * stream, int status)
2799{
2800  fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2801	   program_name);
2802  xexit (status);
2803}
2804
2805int
2806main (int argc, char **argv)
2807{
2808  extern int chdir (char *);
2809  char *srcdir = NULL;
2810  int c;
2811
2812  program_name = *argv;
2813  xmalloc_set_program_name (program_name);
2814
2815  while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2816    switch (c)
2817      {
2818      case OPTION_SRCDIR:
2819	srcdir = optarg;
2820	break;
2821      case 'V':
2822      case 'v':
2823	print_version ();
2824	break;
2825      case 'd':
2826	debug = 1;
2827	break;
2828      case 'h':
2829      case '?':
2830	usage (stderr, 0);
2831      default:
2832      case 0:
2833	break;
2834      }
2835
2836  if (optind != argc)
2837    usage (stdout, 1);
2838
2839  if (srcdir != NULL)
2840    if (chdir (srcdir) != 0)
2841      fail (_("unable to change directory to \"%s\", errno = %s\n"),
2842	    srcdir, strerror (errno));
2843
2844  load_insn_classes ();
2845  load_dependencies ();
2846
2847  shrink (ia64_opcodes_a);
2848  shrink (ia64_opcodes_b);
2849  shrink (ia64_opcodes_f);
2850  shrink (ia64_opcodes_i);
2851  shrink (ia64_opcodes_m);
2852  shrink (ia64_opcodes_x);
2853  shrink (ia64_opcodes_d);
2854
2855  collapse_redundant_completers ();
2856
2857  printf ("/* This file is automatically generated by ia64-gen.  Do not edit!  */\n");
2858  printf ("/* Copyright 2007  Free Software Foundation, Inc.\n\
2859\n\
2860   This file is part of the GNU opcodes library.\n\
2861\n\
2862   This library is free software; you can redistribute it and/or modify\n\
2863   it under the terms of the GNU General Public License as published by\n\
2864   the Free Software Foundation; either version 3, or (at your option)\n\
2865   any later version.\n\
2866\n\
2867   It is distributed in the hope that it will be useful, but WITHOUT\n\
2868   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
2869   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\n\
2870   License for more details.\n\
2871\n\
2872   You should have received a copy of the GNU General Public License\n\
2873   along with this program; see the file COPYING.  If not, write to the\n\
2874   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA\n\
2875   02110-1301, USA.  */\n");
2876
2877  print_string_table ();
2878  print_dependency_table ();
2879  print_completer_table ();
2880  print_main_table ();
2881
2882  generate_disassembler ();
2883
2884  exit (0);
2885}
2886