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