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