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