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