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