opcodes/
[deliverable/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
c10d9d8f 1064 /* All break, nop, and hint variations must match exactly. */
800eeca4
JW
1065 if (resolved &&
1066 (strcmp (ic->name, "break") == 0
c10d9d8f
JW
1067 || strcmp (ic->name, "nop") == 0
1068 || strcmp (ic->name, "hint") == 0))
800eeca4
JW
1069 resolved = strcmp (ic->name, idesc->name) == 0;
1070
bde78a07
NC
1071 /* Assume restrictions in the FORMAT/FIELD negate resolution,
1072 unless specifically allowed by clauses in this block. */
800eeca4
JW
1073 if (resolved && field)
1074 {
bde78a07 1075 /* Check Field(sf)==sN against opcode sN. */
800eeca4
JW
1076 if (strstr(field, "(sf)==") != NULL)
1077 {
1078 char *sf;
bde78a07 1079
800eeca4 1080 if ((sf = strstr (idesc->name, ".s")) != 0)
bde78a07 1081 resolved = strcmp (sf + 1, strstr (field, "==") + 2) == 0;
800eeca4 1082 }
bde78a07 1083 /* Check Field(lftype)==XXX. */
800eeca4
JW
1084 else if (strstr (field, "(lftype)") != NULL)
1085 {
1086 if (strstr (idesc->name, "fault") != NULL)
1087 resolved = strstr (field, "fault") != NULL;
1088 else
1089 resolved = strstr (field, "fault") == NULL;
1090 }
bde78a07 1091 /* Handle Field(ctype)==XXX. */
800eeca4
JW
1092 else if (strstr (field, "(ctype)") != NULL)
1093 {
1094 if (strstr (idesc->name, "or.andcm"))
1095 resolved = strstr (field, "or.andcm") != NULL;
1096 else if (strstr (idesc->name, "and.orcm"))
1097 resolved = strstr (field, "and.orcm") != NULL;
1098 else if (strstr (idesc->name, "orcm"))
1099 resolved = strstr (field, "or orcm") != NULL;
1100 else if (strstr (idesc->name, "or"))
1101 resolved = strstr (field, "or orcm") != NULL;
1102 else if (strstr (idesc->name, "andcm"))
1103 resolved = strstr (field, "and andcm") != NULL;
1104 else if (strstr (idesc->name, "and"))
1105 resolved = strstr (field, "and andcm") != NULL;
1106 else if (strstr (idesc->name, "unc"))
1107 resolved = strstr (field, "unc") != NULL;
1108 else
1109 resolved = strcmp (field, "Field(ctype)==") == 0;
1110 }
1111 }
bde78a07 1112
800eeca4
JW
1113 if (resolved && format)
1114 {
1115 if (strncmp (idesc->name, "dep", 3) == 0
1116 && strstr (format, "I13") != NULL)
1117 resolved = idesc->operands[1] == IA64_OPND_IMM8;
1118 else if (strncmp (idesc->name, "chk", 3) == 0
1119 && strstr (format, "M21") != NULL)
1120 resolved = idesc->operands[0] == IA64_OPND_F2;
1121 else if (strncmp (idesc->name, "lfetch", 6) == 0)
1122 resolved = (strstr (format, "M14 M15") != NULL
1123 && (idesc->operands[1] == IA64_OPND_R2
1124 || idesc->operands[1] == IA64_OPND_IMM9b));
1125 else if (strncmp (idesc->name, "br.call", 7) == 0
1126 && strstr (format, "B5") != NULL)
1127 resolved = idesc->operands[1] == IA64_OPND_B2;
1128 else if (strncmp (idesc->name, "br.call", 7) == 0
1129 && strstr (format, "B3") != NULL)
1130 resolved = idesc->operands[1] == IA64_OPND_TGT25c;
1131 else if (strncmp (idesc->name, "brp", 3) == 0
1132 && strstr (format, "B7") != NULL)
1133 resolved = idesc->operands[0] == IA64_OPND_B2;
1134 else if (strcmp (ic->name, "invala") == 0)
1135 resolved = strcmp (idesc->name, ic->name) == 0;
f4bc6bb0 1136 else if (strncmp (idesc->name, "st", 2) == 0
bad9ceea
JJ
1137 && (strstr (format, "M5") != NULL
1138 || strstr (format, "M10") != NULL))
1139 resolved = idesc->flags & IA64_OPCODE_POSTINC;
1140 else if (strncmp (idesc->name, "ld", 2) == 0
1141 && (strstr (format, "M2 M3") != NULL
1142 || strstr (format, "M12") != NULL
1143 || strstr (format, "M7 M8") != NULL))
f4bc6bb0 1144 resolved = idesc->flags & IA64_OPCODE_POSTINC;
800eeca4
JW
1145 else
1146 resolved = 0;
1147 }
1148
bde78a07
NC
1149 /* Misc brl variations ('.cond' is optional);
1150 plain brl matches brl.cond. */
800eeca4
JW
1151 if (!resolved
1152 && (strcmp (idesc->name, "brl") == 0
1153 || strncmp (idesc->name, "brl.", 4) == 0)
1154 && strcmp (ic->name, "brl.cond") == 0)
1155 {
1156 resolved = 1;
1157 }
1158
bde78a07 1159 /* Misc br variations ('.cond' is optional). */
800eeca4
JW
1160 if (!resolved
1161 && (strcmp (idesc->name, "br") == 0
1162 || strncmp (idesc->name, "br.", 3) == 0)
1163 && strcmp (ic->name, "br.cond") == 0)
1164 {
1165 if (format)
1166 resolved = (strstr (format, "B4") != NULL
1167 && idesc->operands[0] == IA64_OPND_B2)
1168 || (strstr (format, "B1") != NULL
1169 && idesc->operands[0] == IA64_OPND_TGT25c);
1170 else
1171 resolved = 1;
1172 }
1173
bde78a07 1174 /* probe variations. */
800eeca4
JW
1175 if (!resolved && strncmp (idesc->name, "probe", 5) == 0)
1176 {
1177 resolved = strcmp (ic->name, "probe") == 0
1178 && !((strstr (idesc->name, "fault") != NULL)
1179 ^ (format && strstr (format, "M40") != NULL));
1180 }
bde78a07
NC
1181
1182 /* mov variations. */
800eeca4
JW
1183 if (!resolved && is_mov)
1184 {
1185 if (plain_mov)
1186 {
bde78a07 1187 /* mov alias for fmerge. */
800eeca4
JW
1188 if (strcmp (ic->name, "fmerge") == 0)
1189 {
1190 resolved = idesc->operands[0] == IA64_OPND_F1
1191 && idesc->operands[1] == IA64_OPND_F3;
1192 }
bde78a07 1193 /* mov alias for adds (r3 or imm14). */
800eeca4
JW
1194 else if (strcmp (ic->name, "adds") == 0)
1195 {
1196 resolved = (idesc->operands[0] == IA64_OPND_R1
1197 && (idesc->operands[1] == IA64_OPND_R3
1198 || (idesc->operands[1] == IA64_OPND_IMM14)));
1199 }
bde78a07 1200 /* mov alias for addl. */
800eeca4
JW
1201 else if (strcmp (ic->name, "addl") == 0)
1202 {
1203 resolved = idesc->operands[0] == IA64_OPND_R1
1204 && idesc->operands[1] == IA64_OPND_IMM22;
1205 }
1206 }
bde78a07
NC
1207
1208 /* Some variants of mov and mov.[im]. */
800eeca4 1209 if (!resolved && strncmp (ic->name, "mov_", 4) == 0)
bde78a07 1210 resolved = in_iclass_mov_x (idesc, ic, format, field);
800eeca4
JW
1211 }
1212
bde78a07
NC
1213 /* Keep track of this so we can flag any insn classes which aren't
1214 mapped onto at least one real insn. */
800eeca4 1215 if (resolved)
bde78a07 1216 ic->terminal_resolved = 1;
800eeca4 1217 }
bde78a07 1218 else for (i = 0; i < ic->nsubs; i++)
800eeca4 1219 {
bde78a07 1220 if (in_iclass (idesc, ics[ic->subs[i]], format, field, notep))
800eeca4
JW
1221 {
1222 int j;
bde78a07
NC
1223
1224 for (j = 0; j < ic->nxsubs; j++)
1225 if (in_iclass (idesc, ics[ic->xsubs[j]], NULL, NULL, NULL))
1226 return 0;
1227
800eeca4 1228 if (debug > 1)
bde78a07
NC
1229 printf ("%s is in IC %s\n", idesc->name, ic->name);
1230
800eeca4
JW
1231 resolved = 1;
1232 break;
1233 }
1234 }
1235
bde78a07 1236 /* If it's in this IC, add the IC note (if any) to the insn. */
800eeca4
JW
1237 if (resolved)
1238 {
1239 if (ic->note && notep)
1240 {
1241 if (*notep && *notep != ic->note)
bde78a07
NC
1242 warn (_("overwriting note %d with note %d (IC:%s)\n"),
1243 *notep, ic->note, ic->name);
1244
800eeca4
JW
1245 *notep = ic->note;
1246 }
1247 }
1248
1249 return resolved;
1250}
1251
1252\f
1253static int
1254lookup_regindex (const char *name, int specifier)
1255{
1256 switch (specifier)
1257 {
1258 case IA64_RS_ARX:
1259 if (strstr (name, "[RSC]"))
1260 return 16;
1261 if (strstr (name, "[BSP]"))
1262 return 17;
1263 else if (strstr (name, "[BSPSTORE]"))
1264 return 18;
1265 else if (strstr (name, "[RNAT]"))
1266 return 19;
c10d9d8f
JW
1267 else if (strstr (name, "[FCR]"))
1268 return 21;
1269 else if (strstr (name, "[EFLAG]"))
1270 return 24;
1271 else if (strstr (name, "[CSD]"))
1272 return 25;
1273 else if (strstr (name, "[SSD]"))
1274 return 26;
1275 else if (strstr (name, "[CFLG]"))
1276 return 27;
1277 else if (strstr (name, "[FSR]"))
1278 return 28;
1279 else if (strstr (name, "[FIR]"))
1280 return 29;
1281 else if (strstr (name, "[FDR]"))
1282 return 30;
800eeca4
JW
1283 else if (strstr (name, "[CCV]"))
1284 return 32;
1285 else if (strstr (name, "[ITC]"))
1286 return 44;
1287 else if (strstr (name, "[PFS]"))
1288 return 64;
1289 else if (strstr (name, "[LC]"))
1290 return 65;
1291 else if (strstr (name, "[EC]"))
1292 return 66;
1293 abort ();
1294 case IA64_RS_CRX:
1295 if (strstr (name, "[DCR]"))
1296 return 0;
1297 else if (strstr (name, "[ITM]"))
1298 return 1;
1299 else if (strstr (name, "[IVA]"))
1300 return 2;
1301 else if (strstr (name, "[PTA]"))
1302 return 8;
1303 else if (strstr (name, "[GPTA]"))
1304 return 9;
1305 else if (strstr (name, "[IPSR]"))
1306 return 16;
1307 else if (strstr (name, "[ISR]"))
1308 return 17;
1309 else if (strstr (name, "[IIP]"))
1310 return 19;
1311 else if (strstr (name, "[IFA]"))
1312 return 20;
1313 else if (strstr (name, "[ITIR]"))
1314 return 21;
1315 else if (strstr (name, "[IIPA]"))
1316 return 22;
1317 else if (strstr (name, "[IFS]"))
1318 return 23;
1319 else if (strstr (name, "[IIM]"))
1320 return 24;
1321 else if (strstr (name, "[IHA]"))
1322 return 25;
1323 else if (strstr (name, "[LID]"))
1324 return 64;
1325 else if (strstr (name, "[IVR]"))
1326 return 65;
1327 else if (strstr (name, "[TPR]"))
1328 return 66;
1329 else if (strstr (name, "[EOI]"))
1330 return 67;
1331 else if (strstr (name, "[ITV]"))
1332 return 72;
1333 else if (strstr (name, "[PMV]"))
1334 return 73;
1335 else if (strstr (name, "[CMCV]"))
1336 return 74;
1337 abort ();
1338 case IA64_RS_PSR:
1339 if (strstr (name, ".be"))
1340 return 1;
1341 else if (strstr (name, ".up"))
1342 return 2;
1343 else if (strstr (name, ".ac"))
1344 return 3;
1345 else if (strstr (name, ".mfl"))
1346 return 4;
1347 else if (strstr (name, ".mfh"))
1348 return 5;
1349 else if (strstr (name, ".ic"))
1350 return 13;
1351 else if (strstr (name, ".i"))
1352 return 14;
1353 else if (strstr (name, ".pk"))
1354 return 15;
1355 else if (strstr (name, ".dt"))
1356 return 17;
1357 else if (strstr (name, ".dfl"))
1358 return 18;
1359 else if (strstr (name, ".dfh"))
1360 return 19;
1361 else if (strstr (name, ".sp"))
1362 return 20;
1363 else if (strstr (name, ".pp"))
1364 return 21;
1365 else if (strstr (name, ".di"))
1366 return 22;
1367 else if (strstr (name, ".si"))
1368 return 23;
1369 else if (strstr (name, ".db"))
1370 return 24;
1371 else if (strstr (name, ".lp"))
1372 return 25;
1373 else if (strstr (name, ".tb"))
1374 return 26;
1375 else if (strstr (name, ".rt"))
1376 return 27;
1377 else if (strstr (name, ".cpl"))
1378 return 32;
1379 else if (strstr (name, ".rs"))
1380 return 34;
1381 else if (strstr (name, ".mc"))
1382 return 35;
1383 else if (strstr (name, ".it"))
1384 return 36;
1385 else if (strstr (name, ".id"))
1386 return 37;
1387 else if (strstr (name, ".da"))
1388 return 38;
1389 else if (strstr (name, ".dd"))
1390 return 39;
1391 else if (strstr (name, ".ss"))
1392 return 40;
1393 else if (strstr (name, ".ri"))
1394 return 41;
1395 else if (strstr (name, ".ed"))
1396 return 43;
1397 else if (strstr (name, ".bn"))
1398 return 44;
1399 else if (strstr (name, ".ia"))
1400 return 45;
1401 else
1402 abort ();
1403 default:
1404 break;
1405 }
1406 return REG_NONE;
1407}
1408
1409static int
1410lookup_specifier (const char *name)
1411{
1412 if (strchr (name, '%'))
1413 {
1414 if (strstr (name, "AR[K%]") != NULL)
1415 return IA64_RS_AR_K;
1416 if (strstr (name, "AR[UNAT]") != NULL)
1417 return IA64_RS_AR_UNAT;
1418 if (strstr (name, "AR%, % in 8") != NULL)
1419 return IA64_RS_AR;
1420 if (strstr (name, "AR%, % in 48") != NULL)
1421 return IA64_RS_ARb;
1422 if (strstr (name, "BR%") != NULL)
1423 return IA64_RS_BR;
1424 if (strstr (name, "CR[IRR%]") != NULL)
1425 return IA64_RS_CR_IRR;
1426 if (strstr (name, "CR[LRR%]") != NULL)
1427 return IA64_RS_CR_LRR;
1428 if (strstr (name, "CR%") != NULL)
1429 return IA64_RS_CR;
1430 if (strstr (name, "FR%, % in 0") != NULL)
1431 return IA64_RS_FR;
1432 if (strstr (name, "FR%, % in 2") != NULL)
1433 return IA64_RS_FRb;
1434 if (strstr (name, "GR%") != NULL)
1435 return IA64_RS_GR;
139368c9 1436 if (strstr (name, "PR%, % in 1 ") != NULL)
800eeca4 1437 return IA64_RS_PR;
139368c9
JW
1438 if (strstr (name, "PR%, % in 16 ") != NULL)
1439 return IA64_RS_PRr;
800eeca4 1440
bde78a07
NC
1441 warn (_("don't know how to specify %% dependency %s\n"),
1442 name);
800eeca4
JW
1443 }
1444 else if (strchr (name, '#'))
1445 {
1446 if (strstr (name, "CPUID#") != NULL)
1447 return IA64_RS_CPUID;
1448 if (strstr (name, "DBR#") != NULL)
1449 return IA64_RS_DBR;
1450 if (strstr (name, "IBR#") != NULL)
1451 return IA64_RS_IBR;
1452 if (strstr (name, "MSR#") != NULL)
1453 return IA64_RS_MSR;
1454 if (strstr (name, "PKR#") != NULL)
1455 return IA64_RS_PKR;
1456 if (strstr (name, "PMC#") != NULL)
1457 return IA64_RS_PMC;
1458 if (strstr (name, "PMD#") != NULL)
1459 return IA64_RS_PMD;
1460 if (strstr (name, "RR#") != NULL)
1461 return IA64_RS_RR;
1462
bde78a07
NC
1463 warn (_("Don't know how to specify # dependency %s\n"),
1464 name);
800eeca4
JW
1465 }
1466 else if (strncmp (name, "AR[FPSR]", 8) == 0)
1467 return IA64_RS_AR_FPSR;
1468 else if (strncmp (name, "AR[", 3) == 0)
1469 return IA64_RS_ARX;
1470 else if (strncmp (name, "CR[", 3) == 0)
1471 return IA64_RS_CRX;
1472 else if (strncmp (name, "PSR.", 4) == 0)
1473 return IA64_RS_PSR;
1474 else if (strcmp (name, "InService*") == 0)
1475 return IA64_RS_INSERVICE;
1476 else if (strcmp (name, "GR0") == 0)
1477 return IA64_RS_GR0;
1478 else if (strcmp (name, "CFM") == 0)
1479 return IA64_RS_CFM;
1480 else if (strcmp (name, "PR63") == 0)
1481 return IA64_RS_PR63;
1482 else if (strcmp (name, "RSE") == 0)
1483 return IA64_RS_RSE;
1484
1485 return IA64_RS_ANY;
1486}
1487
bde78a07 1488static void
800eeca4
JW
1489print_dependency_table ()
1490{
1491 int i, j;
1492
1493 if (debug)
1494 {
1495 for (i=0;i < iclen;i++)
1496 {
1497 if (ics[i]->is_class)
1498 {
1499 if (!ics[i]->nsubs)
1500 {
800eeca4 1501 if (ics[i]->comment)
bde78a07
NC
1502 warn (_("IC:%s [%s] has no terminals or sub-classes\n"),
1503 ics[i]->name, ics[i]->comment);
1504 else
1505 warn (_("IC:%s has no terminals or sub-classes\n"),
1506 ics[i]->name);
800eeca4
JW
1507 }
1508 }
1509 else
1510 {
1511 if (!ics[i]->terminal_resolved && !ics[i]->orphan)
1512 {
800eeca4 1513 if (ics[i]->comment)
bde78a07
NC
1514 warn (_("no insns mapped directly to terminal IC %s [%s]"),
1515 ics[i]->name, ics[i]->comment);
1516 else
1517 warn (_("no insns mapped directly to terminal IC %s\n"),
1518 ics[i]->name);
800eeca4
JW
1519 }
1520 }
1521 }
1522
bde78a07 1523 for (i = 0; i < iclen; i++)
800eeca4
JW
1524 {
1525 if (ics[i]->orphan)
1526 {
1527 mark_used (ics[i], 1);
bde78a07
NC
1528 warn (_("class %s is defined but not used\n"),
1529 ics[i]->name);
800eeca4
JW
1530 }
1531 }
1532
bde78a07
NC
1533 if (debug > 1)
1534 for (i = 0; i < rdepslen; i++)
1535 {
1536 static const char *mode_str[] = { "RAW", "WAW", "WAR" };
1537
1538 if (rdeps[i]->total_chks == 0)
1539 warn (_("Warning: rsrc %s (%s) has no chks%s\n"),
1540 rdeps[i]->name, mode_str[rdeps[i]->mode],
1541 rdeps[i]->total_regs ? "" : " or regs");
1542 else if (rdeps[i]->total_regs == 0)
1543 warn (_("rsrc %s (%s) has no regs\n"),
1544 rdeps[i]->name, mode_str[rdeps[i]->mode]);
1545 }
800eeca4
JW
1546 }
1547
bde78a07 1548 /* The dependencies themselves. */
800eeca4 1549 printf ("static const struct ia64_dependency\ndependencies[] = {\n");
bde78a07 1550 for (i = 0; i < rdepslen; i++)
800eeca4
JW
1551 {
1552 /* '%', '#', AR[], CR[], or PSR. indicates we need to specify the actual
bde78a07 1553 resource used. */
800eeca4
JW
1554 int specifier = lookup_specifier (rdeps[i]->name);
1555 int regindex = lookup_regindex (rdeps[i]->name, specifier);
1556
1557 printf (" { \"%s\", %d, %d, %d, %d, ",
1558 rdeps[i]->name, specifier,
1559 (int)rdeps[i]->mode, (int)rdeps[i]->semantics, regindex);
1560 if (rdeps[i]->semantics == IA64_DVS_OTHER)
1561 printf ("\"%s\", ", rdeps[i]->extra);
514829c3
JW
1562 else
1563 printf ("NULL, ");
800eeca4
JW
1564 printf("},\n");
1565 }
1566 printf ("};\n\n");
1567
bde78a07 1568 /* And dependency lists. */
800eeca4
JW
1569 for (i=0;i < dlistlen;i++)
1570 {
1571 int len = 2;
1572 printf ("static const short dep%d[] = {\n ", i);
1573 for (j=0;j < dlists[i]->len; j++)
1574 {
1575 len += printf ("%d, ", dlists[i]->deps[j]);
1576 if (len > 75)
1577 {
1578 printf("\n ");
1579 len = 2;
1580 }
1581 }
1582 printf ("\n};\n\n");
1583 }
1584
bde78a07 1585 /* And opcode dependency list. */
800eeca4
JW
1586 printf ("#define NELS(X) (sizeof(X)/sizeof(X[0]))\n");
1587 printf ("static const struct ia64_opcode_dependency\n");
1588 printf ("op_dependencies[] = {\n");
bde78a07 1589 for (i = 0; i < opdeplen; i++)
800eeca4
JW
1590 {
1591 printf (" { ");
1592 if (opdeps[i]->chk == -1)
1593 printf ("0, NULL, ");
1594 else
1595 printf ("NELS(dep%d), dep%d, ", opdeps[i]->chk, opdeps[i]->chk);
1596 if (opdeps[i]->reg == -1)
1597 printf ("0, NULL, ");
1598 else
1599 printf ("NELS(dep%d), dep%d, ", opdeps[i]->reg, opdeps[i]->reg);
1600 printf ("},\n");
1601 }
1602 printf ("};\n\n");
1603}
1604
1605\f
bde78a07 1606/* Add STR to the string table. */
800eeca4 1607static struct string_entry *
bde78a07 1608insert_string (char *str)
800eeca4
JW
1609{
1610 int start = 0, end = strtablen;
1611 int i, x;
1612
1613 if (strtablen == strtabtotlen)
1614 {
1615 strtabtotlen += 20;
1616 string_table = (struct string_entry **)
1617 xrealloc (string_table,
1618 sizeof (struct string_entry **) * strtabtotlen);
1619 }
1620
1621 if (strtablen == 0)
1622 {
1623 strtablen = 1;
1624 string_table[0] = tmalloc (struct string_entry);
1625 string_table[0]->s = xstrdup (str);
1626 string_table[0]->num = 0;
1627 return string_table[0];
1628 }
1629
1630 if (strcmp (str, string_table[strtablen - 1]->s) > 0)
bde78a07 1631 i = end;
800eeca4 1632 else if (strcmp (str, string_table[0]->s) < 0)
bde78a07 1633 i = 0;
800eeca4
JW
1634 else
1635 {
1636 while (1)
1637 {
1638 int c;
1639
1640 i = (start + end) / 2;
1641 c = strcmp (str, string_table[i]->s);
bde78a07 1642
800eeca4 1643 if (c < 0)
bde78a07 1644 end = i - 1;
800eeca4 1645 else if (c == 0)
bde78a07 1646 return string_table[i];
800eeca4 1647 else
bde78a07
NC
1648 start = i + 1;
1649
800eeca4 1650 if (start > end)
bde78a07 1651 break;
800eeca4
JW
1652 }
1653 }
bde78a07 1654
800eeca4 1655 for (; i > 0 && i < strtablen; i--)
bde78a07
NC
1656 if (strcmp (str, string_table[i - 1]->s) > 0)
1657 break;
1658
800eeca4 1659 for (; i < strtablen; i++)
bde78a07
NC
1660 if (strcmp (str, string_table[i]->s) < 0)
1661 break;
1662
800eeca4
JW
1663 for (x = strtablen - 1; x >= i; x--)
1664 {
1665 string_table[x + 1] = string_table[x];
1666 string_table[x + 1]->num = x + 1;
1667 }
bde78a07 1668
800eeca4
JW
1669 string_table[i] = tmalloc (struct string_entry);
1670 string_table[i]->s = xstrdup (str);
1671 string_table[i]->num = i;
1672 strtablen++;
bde78a07 1673
800eeca4
JW
1674 return string_table[i];
1675}
1676\f
bde78a07
NC
1677static struct bittree *
1678make_bittree_entry (void)
800eeca4
JW
1679{
1680 struct bittree *res = tmalloc (struct bittree);
1681
1682 res->disent = NULL;
1683 res->bits[0] = NULL;
1684 res->bits[1] = NULL;
1685 res->bits[2] = NULL;
1686 res->skip_flag = 0;
1687 res->bits_to_skip = 0;
1688 return res;
1689}
bde78a07 1690
800eeca4 1691\f
bde78a07 1692static struct disent *
aa170a07 1693add_dis_table_ent (which, insn, order, completer_index)
800eeca4
JW
1694 struct disent *which;
1695 int insn;
aa170a07 1696 int order;
800eeca4
JW
1697 int completer_index;
1698{
1699 int ci = 0;
1700 struct disent *ent;
1701
1702 if (which != NULL)
1703 {
1704 ent = which;
1705
1706 ent->nextcnt++;
1707 while (ent->nexte != NULL)
bde78a07
NC
1708 ent = ent->nexte;
1709
800eeca4
JW
1710 ent = (ent->nexte = tmalloc (struct disent));
1711 }
1712 else
1713 {
1714 ent = tmalloc (struct disent);
1715 ent->next_ent = disinsntable;
1716 disinsntable = ent;
1717 which = ent;
1718 }
1719 ent->nextcnt = 0;
1720 ent->nexte = NULL;
1721 ent->insn = insn;
aa170a07
TW
1722 ent->priority = order;
1723
800eeca4
JW
1724 while (completer_index != 1)
1725 {
1726 ci = (ci << 1) | (completer_index & 1);
1727 completer_index >>= 1;
1728 }
1729 ent->completer_index = ci;
1730 return which;
1731}
1732\f
bde78a07 1733static void
800eeca4
JW
1734finish_distable ()
1735{
1736 struct disent *ent = disinsntable;
1737 struct disent *prev = ent;
1738
1739 ent->ournum = 32768;
1740 while ((ent = ent->next_ent) != NULL)
1741 {
1742 ent->ournum = prev->ournum + prev->nextcnt + 1;
1743 prev = ent;
1744 }
1745}
1746\f
bde78a07 1747static void
aa170a07
TW
1748insert_bit_table_ent (curr_ent, bit, opcode, mask,
1749 opcodenum, order, completer_index)
800eeca4
JW
1750 struct bittree *curr_ent;
1751 int bit;
1752 ia64_insn opcode;
1753 ia64_insn mask;
1754 int opcodenum;
aa170a07 1755 int order;
800eeca4
JW
1756 int completer_index;
1757{
1758 ia64_insn m;
1759 int b;
1760 struct bittree *next;
1761
1762 if (bit == -1)
1763 {
aa170a07
TW
1764 struct disent *nent = add_dis_table_ent (curr_ent->disent,
1765 opcodenum, order,
800eeca4
JW
1766 completer_index);
1767 curr_ent->disent = nent;
1768 return;
1769 }
1770
1771 m = ((ia64_insn) 1) << bit;
1772
1773 if (mask & m)
bde78a07 1774 b = (opcode & m) ? 1 : 0;
800eeca4 1775 else
bde78a07
NC
1776 b = 2;
1777
800eeca4
JW
1778 next = curr_ent->bits[b];
1779 if (next == NULL)
1780 {
1781 next = make_bittree_entry ();
1782 curr_ent->bits[b] = next;
1783 }
aa170a07 1784 insert_bit_table_ent (next, bit - 1, opcode, mask, opcodenum, order,
800eeca4
JW
1785 completer_index);
1786}
1787\f
bde78a07 1788static void
800eeca4 1789add_dis_entry (first, opcode, mask, opcodenum, ent, completer_index)
aa170a07 1790 struct bittree *first;
800eeca4
JW
1791 ia64_insn opcode;
1792 ia64_insn mask;
1793 int opcodenum;
1794 struct completer_entry *ent;
1795 int completer_index;
1796{
1797 if (completer_index & (1 << 20))
bde78a07 1798 abort ();
c1485d85 1799
800eeca4
JW
1800 while (ent != NULL)
1801 {
1802 ia64_insn newopcode = (opcode & (~ ent->mask)) | ent->bits;
1803 add_dis_entry (first, newopcode, mask, opcodenum, ent->addl_entries,
1804 (completer_index << 1) | 1);
bde78a07 1805
800eeca4
JW
1806 if (ent->is_terminal)
1807 {
aa170a07
TW
1808 insert_bit_table_ent (bittree, 40, newopcode, mask,
1809 opcodenum, opcode_count - ent->order - 1,
800eeca4
JW
1810 (completer_index << 1) | 1);
1811 }
1812 completer_index <<= 1;
1813 ent = ent->alternative;
1814 }
1815}
1816\f
bde78a07
NC
1817/* This optimization pass combines multiple "don't care" nodes. */
1818static void
800eeca4
JW
1819compact_distree (ent)
1820 struct bittree *ent;
1821{
1822#define IS_SKIP(ent) \
1823 ((ent->bits[2] !=NULL) \
1824 && (ent->bits[0] == NULL && ent->bits[1] == NULL && ent->skip_flag == 0))
1825
1826 int bitcnt = 0;
1827 struct bittree *nent = ent;
1828 int x;
1829
1830 while (IS_SKIP (nent))
1831 {
1832 bitcnt++;
1833 nent = nent->bits[2];
1834 }
1835
1836 if (bitcnt)
1837 {
1838 struct bittree *next = ent->bits[2];
1839
1840 ent->bits[0] = nent->bits[0];
1841 ent->bits[1] = nent->bits[1];
1842 ent->bits[2] = nent->bits[2];
1843 ent->disent = nent->disent;
1844 ent->skip_flag = 1;
1845 ent->bits_to_skip = bitcnt;
1846 while (next != nent)
1847 {
1848 struct bittree *b = next;
1849 next = next->bits[2];
1850 free (b);
1851 }
1852 free (nent);
1853 }
1854
1855 for (x = 0; x < 3; x++)
1856 {
1857 struct bittree *i = ent->bits[x];
bde78a07 1858
800eeca4 1859 if (i != NULL)
bde78a07 1860 compact_distree (i);
800eeca4
JW
1861 }
1862}
1863\f
1864static unsigned char *insn_list;
1865static int insn_list_len = 0;
1866static int tot_insn_list_len = 0;
1867
1868/* Generate the disassembler state machine corresponding to the tree
1869 in ENT. */
bde78a07 1870static void
800eeca4
JW
1871gen_dis_table (ent)
1872 struct bittree *ent;
1873{
1874 int x;
1875 int our_offset = insn_list_len;
1876 int bitsused = 5;
1877 int totbits = bitsused;
1878 int needed_bytes;
1879 int zero_count = 0;
bde78a07 1880 int zero_dest = 0; /* Initialize this with 0 to keep gcc quiet... */
800eeca4
JW
1881
1882 /* If this is a terminal entry, there's no point in skipping any
bde78a07 1883 bits. */
800eeca4
JW
1884 if (ent->skip_flag && ent->bits[0] == NULL && ent->bits[1] == NULL &&
1885 ent->bits[2] == NULL)
1886 {
1887 if (ent->disent == NULL)
bde78a07 1888 abort ();
800eeca4 1889 else
bde78a07 1890 ent->skip_flag = 0;
800eeca4
JW
1891 }
1892
1893 /* Calculate the amount of space needed for this entry, or at least
bde78a07 1894 a conservatively large approximation. */
800eeca4 1895 if (ent->skip_flag)
bde78a07
NC
1896 totbits += 5;
1897
800eeca4 1898 for (x = 1; x < 3; x++)
bde78a07
NC
1899 if (ent->bits[x] != NULL)
1900 totbits += 16;
800eeca4
JW
1901
1902 if (ent->disent != NULL)
1903 {
1904 if (ent->bits[2] != NULL)
bde78a07
NC
1905 abort ();
1906
800eeca4
JW
1907 totbits += 16;
1908 }
1909
bde78a07 1910 /* Now allocate the space. */
800eeca4
JW
1911 needed_bytes = (totbits + 7) / 8;
1912 if ((needed_bytes + insn_list_len) > tot_insn_list_len)
1913 {
1914 tot_insn_list_len += 256;
1915 insn_list = (char *) xrealloc (insn_list, tot_insn_list_len);
1916 }
1917 our_offset = insn_list_len;
1918 insn_list_len += needed_bytes;
1919 memset (insn_list + our_offset, 0, needed_bytes);
1920
1921 /* Encode the skip entry by setting bit 6 set in the state op field,
bde78a07 1922 and store the # of bits to skip immediately after. */
800eeca4
JW
1923 if (ent->skip_flag)
1924 {
1925 bitsused += 5;
1926 insn_list[our_offset + 0] |= 0x40 | ((ent->bits_to_skip >> 2) & 0xf);
1927 insn_list[our_offset + 1] |= ((ent->bits_to_skip & 3) << 6);
1928 }
1929
1930#define IS_ONLY_IFZERO(ENT) \
1931 ((ENT)->bits[0] != NULL && (ENT)->bits[1] == NULL && (ENT)->bits[2] == NULL \
1932 && (ENT)->disent == NULL && (ENT)->skip_flag == 0)
1933
1934 /* Store an "if (bit is zero)" instruction by setting bit 7 in the
bde78a07 1935 state op field. */
800eeca4
JW
1936 if (ent->bits[0] != NULL)
1937 {
1938 struct bittree *nent = ent->bits[0];
1939 zero_count = 0;
1940
1941 insn_list[our_offset] |= 0x80;
1942
1943 /* We can encode sequences of multiple "if (bit is zero)" tests
1944 by storing the # of zero bits to check in the lower 3 bits of
1945 the instruction. However, this only applies if the state
1946 solely tests for a zero bit. */
1947
1948 if (IS_ONLY_IFZERO (ent))
1949 {
1950 while (IS_ONLY_IFZERO (nent) && zero_count < 7)
1951 {
1952 nent = nent->bits[0];
1953 zero_count++;
1954 }
1955
1956 insn_list[our_offset + 0] |= zero_count;
1957 }
1958 zero_dest = insn_list_len;
1959 gen_dis_table (nent);
1960 }
1961
1962 /* Now store the remaining tests. We also handle a sole "termination
1963 entry" by storing it as an "any bit" test. */
1964
1965 for (x = 1; x < 3; x++)
1966 {
1967 if (ent->bits[x] != NULL || (x == 2 && ent->disent != NULL))
1968 {
1969 struct bittree *i = ent->bits[x];
1970 int idest;
1971 int currbits = 15;
1972
1973 if (i != NULL)
1974 {
1975 /* If the instruction being branched to only consists of
1976 a termination entry, use the termination entry as the
1977 place to branch to instead. */
1978 if (i->bits[0] == NULL && i->bits[1] == NULL
1979 && i->bits[2] == NULL && i->disent != NULL)
1980 {
1981 idest = i->disent->ournum;
1982 i = NULL;
1983 }
1984 else
bde78a07 1985 idest = insn_list_len - our_offset;
800eeca4
JW
1986 }
1987 else
bde78a07 1988 idest = ent->disent->ournum;
800eeca4
JW
1989
1990 /* If the destination offset for the if (bit is 1) test is less
1991 than 256 bytes away, we can store it as 8-bits instead of 16;
1992 the instruction has bit 5 set for the 16-bit address, and bit
1993 4 for the 8-bit address. Since we've already allocated 16
1994 bits for the address we need to deallocate the space.
1995
1996 Note that branchings within the table are relative, and
1997 there are no branches that branch past our instruction yet
bde78a07 1998 so we do not need to adjust any other offsets. */
800eeca4
JW
1999 if (x == 1)
2000 {
2001 if (idest <= 256)
2002 {
2003 int start = our_offset + bitsused / 8 + 1;
2004
2005 memmove (insn_list + start,
2006 insn_list + start + 1,
2007 insn_list_len - (start + 1));
2008 currbits = 7;
2009 totbits -= 8;
2010 needed_bytes--;
2011 insn_list_len--;
2012 insn_list[our_offset] |= 0x10;
2013 idest--;
2014 }
2015 else
bde78a07 2016 insn_list[our_offset] |= 0x20;
800eeca4
JW
2017 }
2018 else
2019 {
2020 /* An instruction which solely consists of a termination
2021 marker and whose disassembly name index is < 4096
2022 can be stored in 16 bits. The encoding is slightly
2023 odd; the upper 4 bits of the instruction are 0x3, and
2024 bit 3 loses its normal meaning. */
2025
2026 if (ent->bits[0] == NULL && ent->bits[1] == NULL
2027 && ent->bits[2] == NULL && ent->skip_flag == 0
2028 && ent->disent != NULL
2029 && ent->disent->ournum < (32768 + 4096))
2030 {
2031 int start = our_offset + bitsused / 8 + 1;
2032
2033 memmove (insn_list + start,
2034 insn_list + start + 1,
2035 insn_list_len - (start + 1));
2036 currbits = 11;
2037 totbits -= 5;
2038 bitsused--;
2039 needed_bytes--;
2040 insn_list_len--;
2041 insn_list[our_offset] |= 0x30;
2042 idest &= ~32768;
2043 }
2044 else
bde78a07 2045 insn_list[our_offset] |= 0x08;
800eeca4 2046 }
bde78a07 2047
800eeca4
JW
2048 if (debug)
2049 {
2050 int id = idest;
2051
2052 if (i == NULL)
bde78a07 2053 id |= 32768;
800eeca4 2054 else if (! (id & 32768))
bde78a07
NC
2055 id += our_offset;
2056
800eeca4 2057 if (x == 1)
bde78a07 2058 printf ("%d: if (1) goto %d\n", our_offset, id);
800eeca4 2059 else
bde78a07 2060 printf ("%d: try %d\n", our_offset, id);
800eeca4
JW
2061 }
2062
bde78a07 2063 /* Store the address of the entry being branched to. */
800eeca4
JW
2064 while (currbits >= 0)
2065 {
2066 char *byte = insn_list + our_offset + bitsused / 8;
2067
2068 if (idest & (1 << currbits))
bde78a07
NC
2069 *byte |= (1 << (7 - (bitsused % 8)));
2070
800eeca4
JW
2071 bitsused++;
2072 currbits--;
2073 }
2074
bde78a07 2075 /* Now generate the states for the entry being branched to. */
800eeca4 2076 if (i != NULL)
bde78a07 2077 gen_dis_table (i);
800eeca4
JW
2078 }
2079 }
bde78a07 2080
800eeca4
JW
2081 if (debug)
2082 {
2083 if (ent->skip_flag)
bde78a07 2084 printf ("%d: skipping %d\n", our_offset, ent->bits_to_skip);
800eeca4
JW
2085
2086 if (ent->bits[0] != NULL)
bde78a07
NC
2087 printf ("%d: if (0:%d) goto %d\n", our_offset, zero_count + 1,
2088 zero_dest);
800eeca4 2089 }
bde78a07 2090
800eeca4 2091 if (bitsused != totbits)
bde78a07 2092 abort ();
800eeca4
JW
2093}
2094\f
bde78a07
NC
2095static void
2096print_dis_table (void)
800eeca4
JW
2097{
2098 int x;
2099 struct disent *cent = disinsntable;
2100
2101 printf ("static const char dis_table[] = {\n");
2102 for (x = 0; x < insn_list_len; x++)
2103 {
2104 if ((x > 0) && ((x % 12) == 0))
bde78a07
NC
2105 printf ("\n");
2106
800eeca4
JW
2107 printf ("0x%02x, ", insn_list[x]);
2108 }
2109 printf ("\n};\n\n");
2110
2111 printf ("static const struct ia64_dis_names ia64_dis_names[] = {\n");
2112 while (cent != NULL)
2113 {
2114 struct disent *ent = cent;
2115
2116 while (ent != NULL)
2117 {
aa170a07
TW
2118 printf ("{ 0x%x, %d, %d, %d },\n", ent->completer_index,
2119 ent->insn, (ent->nexte != NULL ? 1 : 0),
2120 ent->priority);
800eeca4
JW
2121 ent = ent->nexte;
2122 }
2123 cent = cent->next_ent;
2124 }
2125 printf ("};\n\n");
2126}
2127\f
bde78a07
NC
2128static void
2129generate_disassembler (void)
800eeca4 2130{
aa170a07 2131 int i;
800eeca4
JW
2132
2133 bittree = make_bittree_entry ();
2134
bde78a07 2135 for (i = 0; i < otlen; i++)
800eeca4 2136 {
aa170a07
TW
2137 struct main_entry *ptr = ordered_table[i];
2138
800eeca4 2139 if (ptr->opcode->type != IA64_TYPE_DYN)
bde78a07
NC
2140 add_dis_entry (bittree,
2141 ptr->opcode->opcode, ptr->opcode->mask,
2142 ptr->main_index,
2143 ptr->completers, 1);
800eeca4
JW
2144 }
2145
2146 compact_distree (bittree);
2147 finish_distable ();
2148 gen_dis_table (bittree);
2149
2150 print_dis_table ();
2151}
2152\f
bde78a07
NC
2153static void
2154print_string_table (void)
800eeca4
JW
2155{
2156 int x;
2157 char lbuf[80], buf[80];
2158 int blen = 0;
2159
bde78a07 2160 printf ("static const char * const ia64_strings[] = {\n");
800eeca4 2161 lbuf[0] = '\0';
bde78a07 2162
800eeca4
JW
2163 for (x = 0; x < strtablen; x++)
2164 {
2165 int len;
2166
2167 if (strlen (string_table[x]->s) > 75)
bde78a07
NC
2168 abort ();
2169
800eeca4
JW
2170 sprintf (buf, " \"%s\",", string_table[x]->s);
2171 len = strlen (buf);
bde78a07 2172
800eeca4
JW
2173 if ((blen + len) > 75)
2174 {
2175 printf (" %s\n", lbuf);
2176 lbuf[0] = '\0';
2177 blen = 0;
2178 }
2179 strcat (lbuf, buf);
2180 blen += len;
2181 }
bde78a07 2182
800eeca4 2183 if (blen > 0)
bde78a07
NC
2184 printf (" %s\n", lbuf);
2185
800eeca4
JW
2186 printf ("};\n\n");
2187}
2188\f
2189static struct completer_entry **glist;
2190static int glistlen = 0;
2191static int glisttotlen = 0;
2192
bde78a07 2193/* If the completer trees ENT1 and ENT2 are equal, return 1. */
800eeca4 2194
bde78a07 2195static int
800eeca4
JW
2196completer_entries_eq (ent1, ent2)
2197 struct completer_entry *ent1, *ent2;
2198{
2199 while (ent1 != NULL && ent2 != NULL)
2200 {
2201 if (ent1->name->num != ent2->name->num
2202 || ent1->bits != ent2->bits
2203 || ent1->mask != ent2->mask
2204 || ent1->is_terminal != ent2->is_terminal
aa170a07
TW
2205 || ent1->dependencies != ent2->dependencies
2206 || ent1->order != ent2->order)
bde78a07
NC
2207 return 0;
2208
800eeca4 2209 if (! completer_entries_eq (ent1->addl_entries, ent2->addl_entries))
bde78a07
NC
2210 return 0;
2211
800eeca4
JW
2212 ent1 = ent1->alternative;
2213 ent2 = ent2->alternative;
2214 }
bde78a07 2215
800eeca4
JW
2216 return ent1 == ent2;
2217}
2218\f
2219/* Insert ENT into the global list of completers and return it. If an
2220 equivalent entry (according to completer_entries_eq) already exists,
bde78a07
NC
2221 it is returned instead. */
2222static struct completer_entry *
2223insert_gclist (struct completer_entry *ent)
800eeca4
JW
2224{
2225 if (ent != NULL)
2226 {
2227 int i;
2228 int x;
2229 int start = 0, end;
2230
2231 ent->addl_entries = insert_gclist (ent->addl_entries);
2232 ent->alternative = insert_gclist (ent->alternative);
2233
2234 i = glistlen / 2;
2235 end = glistlen;
2236
2237 if (glisttotlen == glistlen)
2238 {
2239 glisttotlen += 20;
2240 glist = (struct completer_entry **)
2241 xrealloc (glist, sizeof (struct completer_entry *) * glisttotlen);
2242 }
2243
2244 if (glistlen == 0)
2245 {
2246 glist[0] = ent;
2247 glistlen = 1;
2248 return ent;
2249 }
2250
2251 if (ent->name->num < glist[0]->name->num)
bde78a07 2252 i = 0;
800eeca4 2253 else if (ent->name->num > glist[end - 1]->name->num)
bde78a07 2254 i = end;
800eeca4
JW
2255 else
2256 {
2257 int c;
2258
2259 while (1)
2260 {
2261 i = (start + end) / 2;
2262 c = ent->name->num - glist[i]->name->num;
bde78a07 2263
800eeca4 2264 if (c < 0)
bde78a07 2265 end = i - 1;
800eeca4
JW
2266 else if (c == 0)
2267 {
2268 while (i > 0
2269 && ent->name->num == glist[i - 1]->name->num)
bde78a07
NC
2270 i--;
2271
800eeca4
JW
2272 break;
2273 }
2274 else
bde78a07
NC
2275 start = i + 1;
2276
800eeca4 2277 if (start > end)
bde78a07 2278 break;
800eeca4 2279 }
bde78a07 2280
800eeca4
JW
2281 if (c == 0)
2282 {
2283 while (i < glistlen)
2284 {
2285 if (ent->name->num != glist[i]->name->num)
bde78a07
NC
2286 break;
2287
800eeca4 2288 if (completer_entries_eq (ent, glist[i]))
bde78a07
NC
2289 return glist[i];
2290
800eeca4
JW
2291 i++;
2292 }
2293 }
2294 }
bde78a07 2295
800eeca4 2296 for (; i > 0 && i < glistlen; i--)
bde78a07
NC
2297 if (ent->name->num >= glist[i - 1]->name->num)
2298 break;
2299
800eeca4 2300 for (; i < glistlen; i++)
bde78a07
NC
2301 if (ent->name->num < glist[i]->name->num)
2302 break;
2303
800eeca4 2304 for (x = glistlen - 1; x >= i; x--)
bde78a07
NC
2305 glist[x + 1] = glist[x];
2306
800eeca4
JW
2307 glist[i] = ent;
2308 glistlen++;
2309 }
2310 return ent;
2311}
2312\f
2313static int
2314get_prefix_len (name)
2315 const char *name;
2316{
2317 char *c;
2318
2319 if (name[0] == '\0')
bde78a07 2320 return 0;
800eeca4
JW
2321
2322 c = strchr (name, '.');
2323 if (c != NULL)
bde78a07 2324 return c - name;
800eeca4 2325 else
bde78a07 2326 return strlen (name);
800eeca4
JW
2327}
2328\f
2329static void
2330compute_completer_bits (ment, ent)
2331 struct main_entry *ment;
2332 struct completer_entry *ent;
2333{
2334 while (ent != NULL)
2335 {
2336 compute_completer_bits (ment, ent->addl_entries);
2337
2338 if (ent->is_terminal)
2339 {
2340 ia64_insn mask = 0;
2341 ia64_insn our_bits = ent->bits;
2342 struct completer_entry *p = ent->parent;
2343 ia64_insn p_bits;
2344 int x;
2345
2346 while (p != NULL && ! p->is_terminal)
bde78a07 2347 p = p->parent;
800eeca4
JW
2348
2349 if (p != NULL)
bde78a07 2350 p_bits = p->bits;
800eeca4 2351 else
bde78a07 2352 p_bits = ment->opcode->opcode;
800eeca4
JW
2353
2354 for (x = 0; x < 64; x++)
2355 {
2356 ia64_insn m = ((ia64_insn) 1) << x;
bde78a07 2357
800eeca4 2358 if ((p_bits & m) != (our_bits & m))
bde78a07 2359 mask |= m;
800eeca4 2360 else
bde78a07 2361 our_bits &= ~m;
800eeca4
JW
2362 }
2363 ent->bits = our_bits;
2364 ent->mask = mask;
2365 }
2366 else
2367 {
2368 ent->bits = 0;
2369 ent->mask = 0;
2370 }
2371
2372 ent = ent->alternative;
2373 }
2374}
2375\f
2376/* Find identical completer trees that are used in different
bde78a07
NC
2377 instructions and collapse their entries. */
2378static void
2379collapse_redundant_completers (void)
800eeca4
JW
2380{
2381 struct main_entry *ptr;
2382 int x;
2383
2384 for (ptr = maintable; ptr != NULL; ptr = ptr->next)
2385 {
2386 if (ptr->completers == NULL)
bde78a07
NC
2387 abort ();
2388
800eeca4
JW
2389 compute_completer_bits (ptr, ptr->completers);
2390 ptr->completers = insert_gclist (ptr->completers);
2391 }
2392
2393 /* The table has been finalized, now number the indexes. */
2394 for (x = 0; x < glistlen; x++)
bde78a07 2395 glist[x]->num = x;
800eeca4
JW
2396}
2397\f
2398
bde78a07 2399/* Attach two lists of dependencies to each opcode.
800eeca4
JW
2400 1) all resources which, when already marked in use, conflict with this
2401 opcode (chks)
2402 2) all resources which must be marked in use when this opcode is used
bde78a07
NC
2403 (regs). */
2404static int
800eeca4
JW
2405insert_opcode_dependencies (opc, cmp)
2406 struct ia64_opcode *opc;
514829c3 2407 struct completer_entry *cmp ATTRIBUTE_UNUSED;
800eeca4 2408{
bde78a07
NC
2409 /* Note all resources which point to this opcode. rfi has the most chks
2410 (79) and cmpxchng has the most regs (54) so 100 here should be enough. */
800eeca4
JW
2411 int i;
2412 int nregs = 0;
2413 unsigned short regs[256];
2414 int nchks = 0;
2415 unsigned short chks[256];
bde78a07 2416 /* Flag insns for which no class matched; there should be none. */
800eeca4
JW
2417 int no_class_found = 1;
2418
bde78a07 2419 for (i = 0; i < rdepslen; i++)
800eeca4
JW
2420 {
2421 struct rdep *rs = rdeps[i];
2422 int j;
2423
2424 if (strcmp (opc->name, "cmp.eq.and") == 0
2425 && strncmp (rs->name, "PR%", 3) == 0
2426 && rs->mode == 1)
2427 no_class_found = 99;
2428
2429 for (j=0; j < rs->nregs;j++)
2430 {
2431 int ic_note = 0;
2432
2433 if (in_iclass (opc, ics[rs->regs[j]], NULL, NULL, &ic_note))
2434 {
bde78a07 2435 /* We can ignore ic_note 11 for non PR resources. */
800eeca4
JW
2436 if (ic_note == 11 && strncmp (rs->name, "PR", 2) != 0)
2437 ic_note = 0;
2438
2439 if (ic_note != 0 && rs->regnotes[j] != 0
2440 && ic_note != rs->regnotes[j]
2441 && !(ic_note == 11 && rs->regnotes[j] == 1))
bde78a07
NC
2442 warn (_("IC note %d in opcode %s (IC:%s) conflicts with resource %s note %d\n"),
2443 ic_note, opc->name, ics[rs->regs[j]]->name,
2444 rs->name, rs->regnotes[j]);
800eeca4
JW
2445 /* Instruction class notes override resource notes.
2446 So far, only note 11 applies to an IC instead of a resource,
bde78a07 2447 and note 11 implies note 1. */
800eeca4
JW
2448 if (ic_note)
2449 regs[nregs++] = RDEP(ic_note, i);
2450 else
2451 regs[nregs++] = RDEP(rs->regnotes[j], i);
2452 no_class_found = 0;
2453 ++rs->total_regs;
2454 }
2455 }
bde78a07
NC
2456
2457 for (j = 0; j < rs->nchks; j++)
800eeca4
JW
2458 {
2459 int ic_note = 0;
2460
2461 if (in_iclass (opc, ics[rs->chks[j]], NULL, NULL, &ic_note))
2462 {
bde78a07 2463 /* We can ignore ic_note 11 for non PR resources. */
800eeca4
JW
2464 if (ic_note == 11 && strncmp (rs->name, "PR", 2) != 0)
2465 ic_note = 0;
2466
2467 if (ic_note != 0 && rs->chknotes[j] != 0
2468 && ic_note != rs->chknotes[j]
2469 && !(ic_note == 11 && rs->chknotes[j] == 1))
bde78a07
NC
2470 warn (_("IC note %d for opcode %s (IC:%s) conflicts with resource %s note %d\n"),
2471 ic_note, opc->name, ics[rs->chks[j]]->name,
2472 rs->name, rs->chknotes[j]);
800eeca4
JW
2473 if (ic_note)
2474 chks[nchks++] = RDEP(ic_note, i);
2475 else
2476 chks[nchks++] = RDEP(rs->chknotes[j], i);
2477 no_class_found = 0;
2478 ++rs->total_chks;
2479 }
2480 }
2481 }
2482
2483 if (no_class_found)
bde78a07
NC
2484 warn (_("opcode %s has no class (ops %d %d %d)\n"),
2485 opc->name,
2486 opc->operands[0], opc->operands[1], opc->operands[2]);
800eeca4
JW
2487
2488 return insert_dependencies (nchks, chks, nregs, regs);
2489}
2490\f
bde78a07 2491static void
aa170a07 2492insert_completer_entry (opc, tabent, order)
800eeca4
JW
2493 struct ia64_opcode *opc;
2494 struct main_entry *tabent;
aa170a07 2495 int order;
800eeca4
JW
2496{
2497 struct completer_entry **ptr = &tabent->completers;
2498 struct completer_entry *parent = NULL;
2499 char pcopy[129], *prefix;
2500 int at_end = 0;
2501
2502 if (strlen (opc->name) > 128)
bde78a07
NC
2503 abort ();
2504
800eeca4
JW
2505 strcpy (pcopy, opc->name);
2506 prefix = pcopy + get_prefix_len (pcopy);
bde78a07 2507
800eeca4 2508 if (prefix[0] != '\0')
bde78a07 2509 prefix++;
800eeca4
JW
2510
2511 while (! at_end)
2512 {
2513 int need_new_ent = 1;
2514 int plen = get_prefix_len (prefix);
2515 struct string_entry *sent;
2516
2517 at_end = (prefix[plen] == '\0');
2518 prefix[plen] = '\0';
2519 sent = insert_string (prefix);
2520
2521 while (*ptr != NULL)
2522 {
2523 int cmpres = sent->num - (*ptr)->name->num;
2524
2525 if (cmpres == 0)
2526 {
2527 need_new_ent = 0;
2528 break;
2529 }
800eeca4 2530 else
bde78a07 2531 ptr = &((*ptr)->alternative);
800eeca4 2532 }
bde78a07 2533
800eeca4
JW
2534 if (need_new_ent)
2535 {
2536 struct completer_entry *nent = tmalloc (struct completer_entry);
bde78a07 2537
800eeca4
JW
2538 nent->name = sent;
2539 nent->parent = parent;
2540 nent->addl_entries = NULL;
2541 nent->alternative = *ptr;
2542 *ptr = nent;
2543 nent->is_terminal = 0;
2544 nent->dependencies = -1;
2545 }
2546
2547 if (! at_end)
2548 {
2549 parent = *ptr;
2550 ptr = &((*ptr)->addl_entries);
2551 prefix += plen + 1;
2552 }
2553 }
2554
2555 if ((*ptr)->is_terminal)
bde78a07 2556 abort ();
800eeca4
JW
2557
2558 (*ptr)->is_terminal = 1;
2559 (*ptr)->mask = (ia64_insn)-1;
2560 (*ptr)->bits = opc->opcode;
800eeca4 2561 (*ptr)->dependencies = insert_opcode_dependencies (opc, *ptr);
aa170a07 2562 (*ptr)->order = order;
800eeca4
JW
2563}
2564\f
bde78a07 2565static void
800eeca4
JW
2566print_completer_entry (ent)
2567 struct completer_entry *ent;
2568{
2569 int moffset = 0;
2570 ia64_insn mask = ent->mask, bits = ent->bits;
2571
2572 if (mask != 0)
2573 {
2574 while (! (mask & 1))
2575 {
2576 moffset++;
2577 mask = mask >> 1;
2578 bits = bits >> 1;
2579 }
bde78a07 2580
800eeca4 2581 if (bits & 0xffffffff00000000LL)
bde78a07 2582 abort ();
800eeca4
JW
2583 }
2584
2585 printf (" { 0x%x, 0x%x, %d, %d, %d, %d, %d, %d },\n",
2586 (int)bits,
2587 (int)mask,
2588 ent->name->num,
2589 ent->alternative != NULL ? ent->alternative->num : -1,
2590 ent->addl_entries != NULL ? ent->addl_entries->num : -1,
2591 moffset,
2592 ent->is_terminal ? 1 : 0,
2593 ent->dependencies);
2594}
2595\f
bde78a07 2596static void
800eeca4
JW
2597print_completer_table ()
2598{
2599 int x;
2600
2601 printf ("static const struct ia64_completer_table\ncompleter_table[] = {\n");
2602 for (x = 0; x < glistlen; x++)
bde78a07 2603 print_completer_entry (glist[x]);
800eeca4
JW
2604 printf ("};\n\n");
2605}
2606\f
bde78a07 2607static int
800eeca4
JW
2608opcodes_eq (opc1, opc2)
2609 struct ia64_opcode *opc1;
2610 struct ia64_opcode *opc2;
2611{
2612 int x;
2613 int plen1, plen2;
2614
2615 if ((opc1->mask != opc2->mask) || (opc1->type != opc2->type)
2616 || (opc1->num_outputs != opc2->num_outputs)
2617 || (opc1->flags != opc2->flags))
bde78a07
NC
2618 return 0;
2619
800eeca4 2620 for (x = 0; x < 5; x++)
bde78a07
NC
2621 if (opc1->operands[x] != opc2->operands[x])
2622 return 0;
2623
800eeca4
JW
2624 plen1 = get_prefix_len (opc1->name);
2625 plen2 = get_prefix_len (opc2->name);
bde78a07 2626
800eeca4 2627 if (plen1 == plen2 && (memcmp (opc1->name, opc2->name, plen1) == 0))
bde78a07
NC
2628 return 1;
2629
800eeca4
JW
2630 return 0;
2631}
2632\f
bde78a07 2633static void
800eeca4
JW
2634add_opcode_entry (opc)
2635 struct ia64_opcode *opc;
2636{
2637 struct main_entry **place;
2638 struct string_entry *name;
2639 char prefix[129];
2640 int found_it = 0;
2641
2642 if (strlen (opc->name) > 128)
bde78a07
NC
2643 abort ();
2644
800eeca4
JW
2645 place = &maintable;
2646 strcpy (prefix, opc->name);
2647 prefix[get_prefix_len (prefix)] = '\0';
2648 name = insert_string (prefix);
2649
2650 /* Walk the list of opcode table entries. If it's a new
aa170a07 2651 instruction, allocate and fill in a new entry. Note
bde78a07 2652 the main table is alphabetical by opcode name. */
800eeca4
JW
2653
2654 while (*place != NULL)
2655 {
2656 if ((*place)->name->num == name->num
2657 && opcodes_eq ((*place)->opcode, opc))
2658 {
2659 found_it = 1;
2660 break;
2661 }
2662 if ((*place)->name->num > name->num)
bde78a07
NC
2663 break;
2664
800eeca4
JW
2665 place = &((*place)->next);
2666 }
2667 if (! found_it)
2668 {
2669 struct main_entry *nent = tmalloc (struct main_entry);
2670
2671 nent->name = name;
2672 nent->opcode = opc;
2673 nent->next = *place;
2674 nent->completers = 0;
2675 *place = nent;
aa170a07
TW
2676
2677 if (otlen == ottotlen)
2678 {
2679 ottotlen += 20;
2680 ordered_table = (struct main_entry **)
2681 xrealloc (ordered_table, sizeof (struct main_entry *) * ottotlen);
2682 }
2683 ordered_table[otlen++] = nent;
800eeca4 2684 }
c1485d85 2685
aa170a07 2686 insert_completer_entry (opc, *place, opcode_count++);
800eeca4
JW
2687}
2688\f
bde78a07
NC
2689static void
2690print_main_table (void)
800eeca4
JW
2691{
2692 struct main_entry *ptr = maintable;
aa170a07 2693 int index = 0;
800eeca4
JW
2694
2695 printf ("static const struct ia64_main_table\nmain_table[] = {\n");
2696 while (ptr != NULL)
2697 {
514829c3 2698 printf (" { %d, %d, %d, 0x",
800eeca4
JW
2699 ptr->name->num,
2700 ptr->opcode->type,
514829c3
JW
2701 ptr->opcode->num_outputs);
2702 fprintf_vma (stdout, ptr->opcode->opcode);
2703 printf ("ull, 0x");
2704 fprintf_vma (stdout, ptr->opcode->mask);
2705 printf ("ull, { %d, %d, %d, %d, %d }, 0x%x, %d, },\n",
800eeca4
JW
2706 ptr->opcode->operands[0],
2707 ptr->opcode->operands[1],
2708 ptr->opcode->operands[2],
2709 ptr->opcode->operands[3],
2710 ptr->opcode->operands[4],
2711 ptr->opcode->flags,
2712 ptr->completers->num);
2713
aa170a07
TW
2714 ptr->main_index = index++;
2715
800eeca4
JW
2716 ptr = ptr->next;
2717 }
2718 printf ("};\n\n");
2719}
2720\f
bde78a07 2721static void
800eeca4
JW
2722shrink (table)
2723 struct ia64_opcode *table;
2724{
2725 int curr_opcode;
2726
2727 for (curr_opcode = 0; table[curr_opcode].name != NULL; curr_opcode++)
bde78a07 2728 add_opcode_entry (table + curr_opcode);
800eeca4
JW
2729}
2730\f
bde78a07
NC
2731
2732/* Program options. */
2733#define OPTION_SRCDIR 200
2734
2735struct option long_options[] =
2736{
2737 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
2738 {"debug", no_argument, NULL, 'd'},
2739 {"version", no_argument, NULL, 'V'},
2740 {"help", no_argument, NULL, 'h'},
2741 {0, no_argument, NULL, 0}
2742};
2743
2744static void
2745print_version (void)
2746{
2747 printf ("%s: version 1.0\n", program_name);
2748 xexit (0);
2749}
2750
2751static void
2752usage (FILE * stream, int status)
2753{
2754 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2755 program_name);
2756 xexit (status);
2757}
2758
800eeca4 2759int
bde78a07 2760main (int argc, char **argv)
800eeca4 2761{
bde78a07
NC
2762 extern int chdir (char *);
2763 char *srcdir = NULL;
2764 int c;
2765
2766 program_name = *argv;
2767 xmalloc_set_program_name (program_name);
2768
2769 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2770 switch (c)
2771 {
2772 case OPTION_SRCDIR:
2773 srcdir = optarg;
2774 break;
2775 case 'V':
2776 case 'v':
2777 print_version ();
2778 break;
2779 case 'd':
2780 debug = 1;
2781 break;
2782 case 'h':
2783 case '?':
2784 usage (stderr, 0);
2785 default:
2786 case 0:
2787 break;
2788 }
2789
2790 if (optind != argc)
2791 usage (stdout, 1);
2792
2793 if (srcdir != NULL)
2794 if (chdir (srcdir) != 0)
2795 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2796 srcdir, strerror (errno));
800eeca4 2797
bde78a07
NC
2798 load_insn_classes ();
2799 load_dependencies ();
800eeca4
JW
2800
2801 shrink (ia64_opcodes_a);
2802 shrink (ia64_opcodes_b);
2803 shrink (ia64_opcodes_f);
2804 shrink (ia64_opcodes_i);
2805 shrink (ia64_opcodes_m);
2806 shrink (ia64_opcodes_x);
2807 shrink (ia64_opcodes_d);
2808
2809 collapse_redundant_completers ();
2810
bde78a07 2811 printf ("/* This file is automatically generated by ia64-gen. Do not edit! */\n");
800eeca4
JW
2812 print_string_table ();
2813 print_dependency_table ();
2814 print_completer_table ();
2815 print_main_table ();
2816
2817 generate_disassembler ();
2818
2819 exit (0);
2820}
This page took 0.342914 seconds and 4 git commands to generate.