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