PR 6848
[deliverable/binutils-gdb.git] / opcodes / ia64-gen.c
CommitLineData
800eeca4 1/* ia64-gen.c -- Generate a shrunk set of opcode tables
9b201bb5 2 Copyright 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
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
JW
36
37#include <stdio.h>
bde78a07
NC
38#include <stdarg.h>
39#include <errno.h>
800eeca4
JW
40
41#include "ansidecl.h"
42#include "libiberty.h"
3882b010 43#include "safe-ctype.h"
800eeca4 44#include "sysdep.h"
bde78a07 45#include "getopt.h"
800eeca4
JW
46#include "ia64-opc.h"
47#include "ia64-opc-a.c"
48#include "ia64-opc-i.c"
49#include "ia64-opc-m.c"
50#include "ia64-opc-b.c"
51#include "ia64-opc-f.c"
52#include "ia64-opc-x.c"
53#include "ia64-opc-d.c"
54
bde78a07
NC
55#include <libintl.h>
56#define _(String) gettext (String)
57
aa2273ba
JW
58/* This is a copy of fprintf_vma from bfd/bfd-in2.h. We have to use this
59 always, because we might be compiled without BFD64 defined, if configured
60 for a 32-bit target and --enable-targets=all is used. This will work for
61 both 32-bit and 64-bit hosts. */
62#define _opcode_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
63#define _opcode_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
64#define opcode_fprintf_vma(s,x) \
65 fprintf ((s), "%08lx%08lx", _opcode_int64_high (x), _opcode_int64_low (x))
66
bde78a07 67const char * program_name = NULL;
800eeca4
JW
68int debug = 0;
69
60b9a617 70#define NELEMS(a) (sizeof (a) / sizeof ((a)[0]))
800eeca4
JW
71#define tmalloc(X) (X *) xmalloc (sizeof (X))
72
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. */
800eeca4
JW
150 int completer_index;
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);
294static void insert_bit_table_ent (struct bittree *, int, ia64_insn, ia64_insn, int, int, int);
295static void add_dis_entry (struct bittree *, ia64_insn, ia64_insn, int, struct completer_entry *, int);
296static void compact_distree (struct bittree *);
297static struct bittree * make_bittree_entry (void);
298static struct disent * add_dis_table_ent (struct disent *, int, int, int);
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);
573 ics[ind]->subs[0] = fetch_insn_class (subname, 1);;
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
bde78a07
NC
697parse_resource_users (ref, usersp, nusersp, notesp)
698 const char *ref;
800eeca4
JW
699 int **usersp;
700 int *nusersp;
701 int **notesp;
702{
703 int c;
704 char *line = xstrdup (ref);
705 char *tmp = line;
706 int *users = *usersp;
707 int count = *nusersp;
708 int *notes = *notesp;
709
710 c = *tmp;
711 while (c != 0)
712 {
713 char *notestr;
714 int note;
715 char *xsect;
716 int iclass;
717 int create = 0;
718 char *name;
719
3882b010 720 while (ISSPACE (*tmp))
800eeca4
JW
721 ++tmp;
722 name = tmp;
723 while (*tmp && *tmp != ',')
724 ++tmp;
725 c = *tmp;
726 *tmp++ = '\0';
727
bde78a07
NC
728 xsect = strchr (name, '\\');
729 if ((notestr = strstr (name, "+")) != NULL)
800eeca4
JW
730 {
731 char *nextnotestr;
bde78a07 732
800eeca4
JW
733 note = atoi (notestr + 1);
734 if ((nextnotestr = strchr (notestr + 1, '+')) != NULL)
735 {
bde78a07 736 /* Note 13 always implies note 1. */
800eeca4
JW
737 if (strcmp (notestr, "+1+13") == 0)
738 note = 13;
739 else if (!xsect || nextnotestr < xsect)
bde78a07 740 warn (_("multiple note %s not handled\n"), notestr);
800eeca4
JW
741 }
742 if (!xsect)
743 *notestr = '\0';
744 }
745 else
746 note = 0;
bde78a07 747
800eeca4
JW
748 /* All classes are created when the insn class table is parsed;
749 Individual instructions might not appear until the dependency tables
750 are read. Only create new classes if it's *not* an insn class,
751 or if it's a composite class (which wouldn't necessarily be in the IC
bde78a07 752 table). */
0112cd26 753 if (! CONST_STRNEQ (name, "IC:") || xsect != NULL)
800eeca4
JW
754 create = 1;
755
bde78a07 756 iclass = fetch_insn_class (name, create);
800eeca4
JW
757 if (iclass != -1)
758 {
759 users = (int *)
bde78a07 760 xrealloc ((void *) users,(count + 1) * sizeof (int));
800eeca4 761 notes = (int *)
bde78a07 762 xrealloc ((void *) notes,(count + 1) * sizeof (int));
800eeca4
JW
763 notes[count] = note;
764 users[count++] = iclass;
765 mark_used (ics[iclass], 0);
766 }
bde78a07
NC
767 else if (debug)
768 printf("Class %s not found\n", name);
800eeca4 769 }
bde78a07 770 /* Update the return values. */
800eeca4
JW
771 *usersp = users;
772 *nusersp = count;
773 *notesp = notes;
774
775 free (line);
776}
777
778static int
779parse_semantics (char *sem)
780{
781 if (strcmp (sem, "none") == 0)
782 return IA64_DVS_NONE;
783 else if (strcmp (sem, "implied") == 0)
784 return IA64_DVS_IMPLIED;
785 else if (strcmp (sem, "impliedF") == 0)
786 return IA64_DVS_IMPLIEDF;
787 else if (strcmp (sem, "data") == 0)
788 return IA64_DVS_DATA;
789 else if (strcmp (sem, "instr") == 0)
790 return IA64_DVS_INSTR;
791 else if (strcmp (sem, "specific") == 0)
792 return IA64_DVS_SPECIFIC;
139368c9
JW
793 else if (strcmp (sem, "stop") == 0)
794 return IA64_DVS_STOP;
800eeca4
JW
795 else
796 return IA64_DVS_OTHER;
797}
798
799static void
800add_dep (const char *name, const char *chk, const char *reg,
801 int semantics, int mode, char *extra, int flag)
802{
803 struct rdep *rs;
804
805 rs = insert_resource (name, mode);
bde78a07
NC
806
807 parse_resource_users (chk, &rs->chks, &rs->nchks, &rs->chknotes);
808 parse_resource_users (reg, &rs->regs, &rs->nregs, &rs->regnotes);
809
800eeca4
JW
810 rs->semantics = semantics;
811 rs->extra = extra;
812 rs->waw_special = flag;
813}
814
815static void
816load_depfile (const char *filename, enum ia64_dependency_mode mode)
817{
bde78a07 818 FILE *fp = fopen (filename, "r");
800eeca4
JW
819 char buf[1024];
820
bde78a07
NC
821 if (fp == NULL)
822 fail (_("can't find %s for reading\n"), filename);
aa170a07 823
bde78a07
NC
824 fgets (buf, sizeof(buf), fp);
825 while (!feof (fp))
800eeca4
JW
826 {
827 char *name, *tmp;
828 int semantics;
829 char *extra;
830 char *regp, *chkp;
831
832 if (fgets (buf, sizeof(buf), fp) == NULL)
833 break;
834
bde78a07
NC
835 while (ISSPACE (buf[strlen (buf) - 1]))
836 buf[strlen (buf) - 1] = '\0';
800eeca4
JW
837
838 name = tmp = buf;
839 while (*tmp != ';')
840 ++tmp;
841 *tmp++ = '\0';
842
3882b010 843 while (ISSPACE (*tmp))
800eeca4
JW
844 ++tmp;
845 regp = tmp;
846 tmp = strchr (tmp, ';');
847 if (!tmp)
848 abort ();
849 *tmp++ = 0;
3882b010 850 while (ISSPACE (*tmp))
800eeca4
JW
851 ++tmp;
852 chkp = tmp;
853 tmp = strchr (tmp, ';');
854 if (!tmp)
855 abort ();
856 *tmp++ = 0;
3882b010 857 while (ISSPACE (*tmp))
800eeca4
JW
858 ++tmp;
859 semantics = parse_semantics (tmp);
860 extra = semantics == IA64_DVS_OTHER ? xstrdup (tmp) : NULL;
861
862 /* For WAW entries, if the chks and regs differ, we need to enter the
863 entries in both positions so that the tables will be parsed properly,
bde78a07 864 without a lot of extra work. */
800eeca4
JW
865 if (mode == IA64_DV_WAW && strcmp (regp, chkp) != 0)
866 {
867 add_dep (name, chkp, regp, semantics, mode, extra, 0);
868 add_dep (name, regp, chkp, semantics, mode, extra, 1);
869 }
870 else
871 {
872 add_dep (name, chkp, regp, semantics, mode, extra, 0);
873 }
874 }
bde78a07 875 fclose (fp);
800eeca4
JW
876}
877
878static void
bde78a07 879load_dependencies (void)
800eeca4
JW
880{
881 load_depfile ("ia64-raw.tbl", IA64_DV_RAW);
882 load_depfile ("ia64-waw.tbl", IA64_DV_WAW);
883 load_depfile ("ia64-war.tbl", IA64_DV_WAR);
884
885 if (debug)
bde78a07 886 printf ("%d RAW/WAW/WAR dependencies\n", rdepslen);
800eeca4
JW
887}
888
bde78a07 889/* Is the given operand an indirect register file operand? */
800eeca4
JW
890static int
891irf_operand (int op, const char *field)
892{
893 if (!field)
894 {
895 return op == IA64_OPND_RR_R3 || op == IA64_OPND_DBR_R3
c1485d85
NC
896 || op == IA64_OPND_IBR_R3 || op == IA64_OPND_PKR_R3
897 || op == IA64_OPND_PMC_R3 || op == IA64_OPND_PMD_R3
800eeca4
JW
898 || op == IA64_OPND_MSR_R3 || op == IA64_OPND_CPUID_R3;
899 }
900 else
901 {
902 return ((op == IA64_OPND_RR_R3 && strstr (field, "rr"))
903 || (op == IA64_OPND_DBR_R3 && strstr (field, "dbr"))
904 || (op == IA64_OPND_IBR_R3 && strstr (field, "ibr"))
905 || (op == IA64_OPND_PKR_R3 && strstr (field, "pkr"))
906 || (op == IA64_OPND_PMC_R3 && strstr (field, "pmc"))
907 || (op == IA64_OPND_PMD_R3 && strstr (field, "pmd"))
908 || (op == IA64_OPND_MSR_R3 && strstr (field, "msr"))
909 || (op == IA64_OPND_CPUID_R3 && strstr (field, "cpuid")));
910 }
911}
912
bde78a07
NC
913/* Handle mov_ar, mov_br, mov_cr, mov_indirect, mov_ip, mov_pr, mov_psr, and
914 mov_um insn classes. */
800eeca4
JW
915static int
916in_iclass_mov_x (struct ia64_opcode *idesc, struct iclass *ic,
917 const char *format, const char *field)
918{
919 int plain_mov = strcmp (idesc->name, "mov") == 0;
920
921 if (!format)
922 return 0;
923
924 switch (ic->name[4])
925 {
926 default:
927 abort ();
928 case 'a':
929 {
930 int i = strcmp (idesc->name, "mov.i") == 0;
931 int m = strcmp (idesc->name, "mov.m") == 0;
932 int i2627 = i && idesc->operands[0] == IA64_OPND_AR3;
933 int i28 = i && idesc->operands[1] == IA64_OPND_AR3;
934 int m2930 = m && idesc->operands[0] == IA64_OPND_AR3;
935 int m31 = m && idesc->operands[1] == IA64_OPND_AR3;
936 int pseudo0 = plain_mov && idesc->operands[1] == IA64_OPND_AR3;
937 int pseudo1 = plain_mov && idesc->operands[0] == IA64_OPND_AR3;
938
939 /* IC:mov ar */
940 if (i2627)
941 return strstr (format, "I26") || strstr (format, "I27");
942 if (i28)
943 return strstr (format, "I28") != NULL;
944 if (m2930)
945 return strstr (format, "M29") || strstr (format, "M30");
946 if (m31)
947 return strstr (format, "M31") != NULL;
948 if (pseudo0 || pseudo1)
949 return 1;
950 }
951 break;
952 case 'b':
953 {
954 int i21 = idesc->operands[0] == IA64_OPND_B1;
955 int i22 = plain_mov && idesc->operands[1] == IA64_OPND_B2;
956 if (i22)
957 return strstr (format, "I22") != NULL;
958 if (i21)
959 return strstr (format, "I21") != NULL;
960 }
961 break;
962 case 'c':
963 {
964 int m32 = plain_mov && idesc->operands[0] == IA64_OPND_CR3;
965 int m33 = plain_mov && idesc->operands[1] == IA64_OPND_CR3;
966 if (m32)
967 return strstr (format, "M32") != NULL;
968 if (m33)
969 return strstr (format, "M33") != NULL;
970 }
971 break;
972 case 'i':
973 if (ic->name[5] == 'n')
974 {
975 int m42 = plain_mov && irf_operand (idesc->operands[0], field);
976 int m43 = plain_mov && irf_operand (idesc->operands[1], field);
977 if (m42)
978 return strstr (format, "M42") != NULL;
979 if (m43)
980 return strstr (format, "M43") != NULL;
981 }
982 else if (ic->name[5] == 'p')
983 {
984 return idesc->operands[1] == IA64_OPND_IP;
985 }
986 else
987 abort ();
988 break;
989 case 'p':
990 if (ic->name[5] == 'r')
991 {
992 int i25 = plain_mov && idesc->operands[1] == IA64_OPND_PR;
993 int i23 = plain_mov && idesc->operands[0] == IA64_OPND_PR;
994 int i24 = plain_mov && idesc->operands[0] == IA64_OPND_PR_ROT;
995 if (i23)
996 return strstr (format, "I23") != NULL;
997 if (i24)
998 return strstr (format, "I24") != NULL;
999 if (i25)
1000 return strstr (format, "I25") != NULL;
1001 }
1002 else if (ic->name[5] == 's')
1003 {
1004 int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_L;
1005 int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR;
1006 if (m35)
1007 return strstr (format, "M35") != NULL;
1008 if (m36)
1009 return strstr (format, "M36") != NULL;
1010 }
1011 else
1012 abort ();
1013 break;
1014 case 'u':
1015 {
1016 int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_UM;
1017 int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR_UM;
1018 if (m35)
1019 return strstr (format, "M35") != NULL;
1020 if (m36)
1021 return strstr (format, "M36") != NULL;
1022 }
1023 break;
1024 }
1025 return 0;
1026}
1027
bde78a07 1028/* Is the given opcode in the given insn class? */
800eeca4 1029static int
bde78a07
NC
1030in_iclass (struct ia64_opcode *idesc, struct iclass *ic,
1031 const char *format, const char *field, int *notep)
800eeca4
JW
1032{
1033 int i;
1034 int resolved = 0;
1035
1036 if (ic->comment)
1037 {
0112cd26 1038 if (CONST_STRNEQ (ic->comment, "Format"))
800eeca4 1039 {
bde78a07
NC
1040 /* Assume that the first format seen is the most restrictive, and
1041 only keep a later one if it looks like it's more restrictive. */
800eeca4
JW
1042 if (format)
1043 {
1044 if (strlen (ic->comment) < strlen (format))
1045 {
bde78a07
NC
1046 warn (_("most recent format '%s'\nappears more restrictive than '%s'\n"),
1047 ic->comment, format);
800eeca4
JW
1048 format = ic->comment;
1049 }
1050 }
1051 else
1052 format = ic->comment;
1053 }
0112cd26 1054 else if (CONST_STRNEQ (ic->comment, "Field"))
800eeca4
JW
1055 {
1056 if (field)
bde78a07
NC
1057 warn (_("overlapping field %s->%s\n"),
1058 ic->comment, field);
800eeca4
JW
1059 field = ic->comment;
1060 }
1061 }
1062
bde78a07 1063 /* An insn class matches anything that is the same followed by completers,
800eeca4 1064 except when the absence and presence of completers constitutes different
bde78a07 1065 instructions. */
800eeca4
JW
1066 if (ic->nsubs == 0 && ic->nxsubs == 0)
1067 {
0112cd26 1068 int is_mov = CONST_STRNEQ (idesc->name, "mov");
800eeca4
JW
1069 int plain_mov = strcmp (idesc->name, "mov") == 0;
1070 int len = strlen(ic->name);
1071
1072 resolved = ((strncmp (ic->name, idesc->name, len) == 0)
1073 && (idesc->name[len] == '\0'
1074 || idesc->name[len] == '.'));
1075
c10d9d8f 1076 /* All break, nop, and hint variations must match exactly. */
800eeca4
JW
1077 if (resolved &&
1078 (strcmp (ic->name, "break") == 0
c10d9d8f
JW
1079 || strcmp (ic->name, "nop") == 0
1080 || strcmp (ic->name, "hint") == 0))
800eeca4
JW
1081 resolved = strcmp (ic->name, idesc->name) == 0;
1082
bde78a07
NC
1083 /* Assume restrictions in the FORMAT/FIELD negate resolution,
1084 unless specifically allowed by clauses in this block. */
800eeca4
JW
1085 if (resolved && field)
1086 {
bde78a07 1087 /* Check Field(sf)==sN against opcode sN. */
800eeca4
JW
1088 if (strstr(field, "(sf)==") != NULL)
1089 {
1090 char *sf;
bde78a07 1091
800eeca4 1092 if ((sf = strstr (idesc->name, ".s")) != 0)
bde78a07 1093 resolved = strcmp (sf + 1, strstr (field, "==") + 2) == 0;
800eeca4 1094 }
bde78a07 1095 /* Check Field(lftype)==XXX. */
800eeca4
JW
1096 else if (strstr (field, "(lftype)") != NULL)
1097 {
1098 if (strstr (idesc->name, "fault") != NULL)
1099 resolved = strstr (field, "fault") != NULL;
1100 else
1101 resolved = strstr (field, "fault") == NULL;
1102 }
bde78a07 1103 /* Handle Field(ctype)==XXX. */
800eeca4
JW
1104 else if (strstr (field, "(ctype)") != NULL)
1105 {
1106 if (strstr (idesc->name, "or.andcm"))
1107 resolved = strstr (field, "or.andcm") != NULL;
1108 else if (strstr (idesc->name, "and.orcm"))
1109 resolved = strstr (field, "and.orcm") != NULL;
1110 else if (strstr (idesc->name, "orcm"))
1111 resolved = strstr (field, "or orcm") != NULL;
1112 else if (strstr (idesc->name, "or"))
1113 resolved = strstr (field, "or orcm") != NULL;
1114 else if (strstr (idesc->name, "andcm"))
1115 resolved = strstr (field, "and andcm") != NULL;
1116 else if (strstr (idesc->name, "and"))
1117 resolved = strstr (field, "and andcm") != NULL;
1118 else if (strstr (idesc->name, "unc"))
1119 resolved = strstr (field, "unc") != NULL;
1120 else
1121 resolved = strcmp (field, "Field(ctype)==") == 0;
1122 }
1123 }
bde78a07 1124
800eeca4
JW
1125 if (resolved && format)
1126 {
0112cd26 1127 if (CONST_STRNEQ (idesc->name, "dep")
800eeca4
JW
1128 && strstr (format, "I13") != NULL)
1129 resolved = idesc->operands[1] == IA64_OPND_IMM8;
0112cd26 1130 else if (CONST_STRNEQ (idesc->name, "chk")
800eeca4
JW
1131 && strstr (format, "M21") != NULL)
1132 resolved = idesc->operands[0] == IA64_OPND_F2;
0112cd26 1133 else if (CONST_STRNEQ (idesc->name, "lfetch"))
800eeca4
JW
1134 resolved = (strstr (format, "M14 M15") != NULL
1135 && (idesc->operands[1] == IA64_OPND_R2
1136 || idesc->operands[1] == IA64_OPND_IMM9b));
0112cd26 1137 else if (CONST_STRNEQ (idesc->name, "br.call")
800eeca4
JW
1138 && strstr (format, "B5") != NULL)
1139 resolved = idesc->operands[1] == IA64_OPND_B2;
0112cd26 1140 else if (CONST_STRNEQ (idesc->name, "br.call")
800eeca4
JW
1141 && strstr (format, "B3") != NULL)
1142 resolved = idesc->operands[1] == IA64_OPND_TGT25c;
0112cd26 1143 else if (CONST_STRNEQ (idesc->name, "brp")
800eeca4
JW
1144 && strstr (format, "B7") != NULL)
1145 resolved = idesc->operands[0] == IA64_OPND_B2;
1146 else if (strcmp (ic->name, "invala") == 0)
1147 resolved = strcmp (idesc->name, ic->name) == 0;
0112cd26 1148 else if (CONST_STRNEQ (idesc->name, "st")
bad9ceea
JJ
1149 && (strstr (format, "M5") != NULL
1150 || strstr (format, "M10") != NULL))
1151 resolved = idesc->flags & IA64_OPCODE_POSTINC;
0112cd26 1152 else if (CONST_STRNEQ (idesc->name, "ld")
bad9ceea
JJ
1153 && (strstr (format, "M2 M3") != NULL
1154 || strstr (format, "M12") != NULL
1155 || strstr (format, "M7 M8") != NULL))
f4bc6bb0 1156 resolved = idesc->flags & IA64_OPCODE_POSTINC;
800eeca4
JW
1157 else
1158 resolved = 0;
1159 }
1160
bde78a07
NC
1161 /* Misc brl variations ('.cond' is optional);
1162 plain brl matches brl.cond. */
800eeca4
JW
1163 if (!resolved
1164 && (strcmp (idesc->name, "brl") == 0
0112cd26 1165 || CONST_STRNEQ (idesc->name, "brl."))
800eeca4
JW
1166 && strcmp (ic->name, "brl.cond") == 0)
1167 {
1168 resolved = 1;
1169 }
1170
bde78a07 1171 /* Misc br variations ('.cond' is optional). */
800eeca4
JW
1172 if (!resolved
1173 && (strcmp (idesc->name, "br") == 0
0112cd26 1174 || CONST_STRNEQ (idesc->name, "br."))
800eeca4
JW
1175 && strcmp (ic->name, "br.cond") == 0)
1176 {
1177 if (format)
1178 resolved = (strstr (format, "B4") != NULL
1179 && idesc->operands[0] == IA64_OPND_B2)
1180 || (strstr (format, "B1") != NULL
1181 && idesc->operands[0] == IA64_OPND_TGT25c);
1182 else
1183 resolved = 1;
1184 }
1185
bde78a07 1186 /* probe variations. */
0112cd26 1187 if (!resolved && CONST_STRNEQ (idesc->name, "probe"))
800eeca4
JW
1188 {
1189 resolved = strcmp (ic->name, "probe") == 0
1190 && !((strstr (idesc->name, "fault") != NULL)
1191 ^ (format && strstr (format, "M40") != NULL));
1192 }
bde78a07
NC
1193
1194 /* mov variations. */
800eeca4
JW
1195 if (!resolved && is_mov)
1196 {
1197 if (plain_mov)
1198 {
bde78a07 1199 /* mov alias for fmerge. */
800eeca4
JW
1200 if (strcmp (ic->name, "fmerge") == 0)
1201 {
1202 resolved = idesc->operands[0] == IA64_OPND_F1
1203 && idesc->operands[1] == IA64_OPND_F3;
1204 }
bde78a07 1205 /* mov alias for adds (r3 or imm14). */
800eeca4
JW
1206 else if (strcmp (ic->name, "adds") == 0)
1207 {
1208 resolved = (idesc->operands[0] == IA64_OPND_R1
1209 && (idesc->operands[1] == IA64_OPND_R3
1210 || (idesc->operands[1] == IA64_OPND_IMM14)));
1211 }
bde78a07 1212 /* mov alias for addl. */
800eeca4
JW
1213 else if (strcmp (ic->name, "addl") == 0)
1214 {
1215 resolved = idesc->operands[0] == IA64_OPND_R1
1216 && idesc->operands[1] == IA64_OPND_IMM22;
1217 }
1218 }
bde78a07
NC
1219
1220 /* Some variants of mov and mov.[im]. */
0112cd26 1221 if (!resolved && CONST_STRNEQ (ic->name, "mov_"))
bde78a07 1222 resolved = in_iclass_mov_x (idesc, ic, format, field);
800eeca4
JW
1223 }
1224
bde78a07
NC
1225 /* Keep track of this so we can flag any insn classes which aren't
1226 mapped onto at least one real insn. */
800eeca4 1227 if (resolved)
bde78a07 1228 ic->terminal_resolved = 1;
800eeca4 1229 }
bde78a07 1230 else for (i = 0; i < ic->nsubs; i++)
800eeca4 1231 {
bde78a07 1232 if (in_iclass (idesc, ics[ic->subs[i]], format, field, notep))
800eeca4
JW
1233 {
1234 int j;
bde78a07
NC
1235
1236 for (j = 0; j < ic->nxsubs; j++)
1237 if (in_iclass (idesc, ics[ic->xsubs[j]], NULL, NULL, NULL))
1238 return 0;
1239
800eeca4 1240 if (debug > 1)
bde78a07
NC
1241 printf ("%s is in IC %s\n", idesc->name, ic->name);
1242
800eeca4
JW
1243 resolved = 1;
1244 break;
1245 }
1246 }
1247
bde78a07 1248 /* If it's in this IC, add the IC note (if any) to the insn. */
800eeca4
JW
1249 if (resolved)
1250 {
1251 if (ic->note && notep)
1252 {
1253 if (*notep && *notep != ic->note)
bde78a07
NC
1254 warn (_("overwriting note %d with note %d (IC:%s)\n"),
1255 *notep, ic->note, ic->name);
1256
800eeca4
JW
1257 *notep = ic->note;
1258 }
1259 }
1260
1261 return resolved;
1262}
1263
1264\f
1265static int
1266lookup_regindex (const char *name, int specifier)
1267{
1268 switch (specifier)
1269 {
1270 case IA64_RS_ARX:
1271 if (strstr (name, "[RSC]"))
1272 return 16;
1273 if (strstr (name, "[BSP]"))
1274 return 17;
1275 else if (strstr (name, "[BSPSTORE]"))
1276 return 18;
1277 else if (strstr (name, "[RNAT]"))
1278 return 19;
c10d9d8f
JW
1279 else if (strstr (name, "[FCR]"))
1280 return 21;
1281 else if (strstr (name, "[EFLAG]"))
1282 return 24;
1283 else if (strstr (name, "[CSD]"))
1284 return 25;
1285 else if (strstr (name, "[SSD]"))
1286 return 26;
1287 else if (strstr (name, "[CFLG]"))
1288 return 27;
1289 else if (strstr (name, "[FSR]"))
1290 return 28;
1291 else if (strstr (name, "[FIR]"))
1292 return 29;
1293 else if (strstr (name, "[FDR]"))
1294 return 30;
800eeca4
JW
1295 else if (strstr (name, "[CCV]"))
1296 return 32;
1297 else if (strstr (name, "[ITC]"))
1298 return 44;
4f8631b1
L
1299 else if (strstr (name, "[RUC]"))
1300 return 45;
800eeca4
JW
1301 else if (strstr (name, "[PFS]"))
1302 return 64;
1303 else if (strstr (name, "[LC]"))
1304 return 65;
1305 else if (strstr (name, "[EC]"))
1306 return 66;
1307 abort ();
1308 case IA64_RS_CRX:
1309 if (strstr (name, "[DCR]"))
1310 return 0;
1311 else if (strstr (name, "[ITM]"))
1312 return 1;
1313 else if (strstr (name, "[IVA]"))
1314 return 2;
1315 else if (strstr (name, "[PTA]"))
1316 return 8;
1317 else if (strstr (name, "[GPTA]"))
1318 return 9;
1319 else if (strstr (name, "[IPSR]"))
1320 return 16;
1321 else if (strstr (name, "[ISR]"))
1322 return 17;
1323 else if (strstr (name, "[IIP]"))
1324 return 19;
1325 else if (strstr (name, "[IFA]"))
1326 return 20;
1327 else if (strstr (name, "[ITIR]"))
1328 return 21;
1329 else if (strstr (name, "[IIPA]"))
1330 return 22;
1331 else if (strstr (name, "[IFS]"))
1332 return 23;
1333 else if (strstr (name, "[IIM]"))
1334 return 24;
1335 else if (strstr (name, "[IHA]"))
1336 return 25;
1337 else if (strstr (name, "[LID]"))
1338 return 64;
1339 else if (strstr (name, "[IVR]"))
1340 return 65;
1341 else if (strstr (name, "[TPR]"))
1342 return 66;
1343 else if (strstr (name, "[EOI]"))
1344 return 67;
1345 else if (strstr (name, "[ITV]"))
1346 return 72;
1347 else if (strstr (name, "[PMV]"))
1348 return 73;
1349 else if (strstr (name, "[CMCV]"))
1350 return 74;
1351 abort ();
1352 case IA64_RS_PSR:
1353 if (strstr (name, ".be"))
1354 return 1;
1355 else if (strstr (name, ".up"))
1356 return 2;
1357 else if (strstr (name, ".ac"))
1358 return 3;
1359 else if (strstr (name, ".mfl"))
1360 return 4;
1361 else if (strstr (name, ".mfh"))
1362 return 5;
1363 else if (strstr (name, ".ic"))
1364 return 13;
1365 else if (strstr (name, ".i"))
1366 return 14;
1367 else if (strstr (name, ".pk"))
1368 return 15;
1369 else if (strstr (name, ".dt"))
1370 return 17;
1371 else if (strstr (name, ".dfl"))
1372 return 18;
1373 else if (strstr (name, ".dfh"))
1374 return 19;
1375 else if (strstr (name, ".sp"))
1376 return 20;
1377 else if (strstr (name, ".pp"))
1378 return 21;
1379 else if (strstr (name, ".di"))
1380 return 22;
1381 else if (strstr (name, ".si"))
1382 return 23;
1383 else if (strstr (name, ".db"))
1384 return 24;
1385 else if (strstr (name, ".lp"))
1386 return 25;
1387 else if (strstr (name, ".tb"))
1388 return 26;
1389 else if (strstr (name, ".rt"))
1390 return 27;
1391 else if (strstr (name, ".cpl"))
1392 return 32;
1393 else if (strstr (name, ".rs"))
1394 return 34;
1395 else if (strstr (name, ".mc"))
1396 return 35;
1397 else if (strstr (name, ".it"))
1398 return 36;
1399 else if (strstr (name, ".id"))
1400 return 37;
1401 else if (strstr (name, ".da"))
1402 return 38;
1403 else if (strstr (name, ".dd"))
1404 return 39;
1405 else if (strstr (name, ".ss"))
1406 return 40;
1407 else if (strstr (name, ".ri"))
1408 return 41;
1409 else if (strstr (name, ".ed"))
1410 return 43;
1411 else if (strstr (name, ".bn"))
1412 return 44;
1413 else if (strstr (name, ".ia"))
1414 return 45;
7f3dfb9c
L
1415 else if (strstr (name, ".vm"))
1416 return 46;
800eeca4
JW
1417 else
1418 abort ();
1419 default:
1420 break;
1421 }
1422 return REG_NONE;
1423}
1424
1425static int
1426lookup_specifier (const char *name)
1427{
1428 if (strchr (name, '%'))
1429 {
1430 if (strstr (name, "AR[K%]") != NULL)
1431 return IA64_RS_AR_K;
1432 if (strstr (name, "AR[UNAT]") != NULL)
1433 return IA64_RS_AR_UNAT;
1434 if (strstr (name, "AR%, % in 8") != NULL)
1435 return IA64_RS_AR;
1436 if (strstr (name, "AR%, % in 48") != NULL)
1437 return IA64_RS_ARb;
1438 if (strstr (name, "BR%") != NULL)
1439 return IA64_RS_BR;
1440 if (strstr (name, "CR[IRR%]") != NULL)
1441 return IA64_RS_CR_IRR;
1442 if (strstr (name, "CR[LRR%]") != NULL)
1443 return IA64_RS_CR_LRR;
1444 if (strstr (name, "CR%") != NULL)
1445 return IA64_RS_CR;
1446 if (strstr (name, "FR%, % in 0") != NULL)
1447 return IA64_RS_FR;
1448 if (strstr (name, "FR%, % in 2") != NULL)
1449 return IA64_RS_FRb;
1450 if (strstr (name, "GR%") != NULL)
1451 return IA64_RS_GR;
139368c9 1452 if (strstr (name, "PR%, % in 1 ") != NULL)
800eeca4 1453 return IA64_RS_PR;
139368c9
JW
1454 if (strstr (name, "PR%, % in 16 ") != NULL)
1455 return IA64_RS_PRr;
800eeca4 1456
bde78a07
NC
1457 warn (_("don't know how to specify %% dependency %s\n"),
1458 name);
800eeca4
JW
1459 }
1460 else if (strchr (name, '#'))
1461 {
1462 if (strstr (name, "CPUID#") != NULL)
1463 return IA64_RS_CPUID;
1464 if (strstr (name, "DBR#") != NULL)
1465 return IA64_RS_DBR;
1466 if (strstr (name, "IBR#") != NULL)
1467 return IA64_RS_IBR;
1468 if (strstr (name, "MSR#") != NULL)
1469 return IA64_RS_MSR;
1470 if (strstr (name, "PKR#") != NULL)
1471 return IA64_RS_PKR;
1472 if (strstr (name, "PMC#") != NULL)
1473 return IA64_RS_PMC;
1474 if (strstr (name, "PMD#") != NULL)
1475 return IA64_RS_PMD;
1476 if (strstr (name, "RR#") != NULL)
1477 return IA64_RS_RR;
1478
bde78a07
NC
1479 warn (_("Don't know how to specify # dependency %s\n"),
1480 name);
800eeca4 1481 }
0112cd26 1482 else if (CONST_STRNEQ (name, "AR[FPSR]"))
800eeca4 1483 return IA64_RS_AR_FPSR;
0112cd26 1484 else if (CONST_STRNEQ (name, "AR["))
800eeca4 1485 return IA64_RS_ARX;
0112cd26 1486 else if (CONST_STRNEQ (name, "CR["))
800eeca4 1487 return IA64_RS_CRX;
0112cd26 1488 else if (CONST_STRNEQ (name, "PSR."))
800eeca4
JW
1489 return IA64_RS_PSR;
1490 else if (strcmp (name, "InService*") == 0)
1491 return IA64_RS_INSERVICE;
1492 else if (strcmp (name, "GR0") == 0)
1493 return IA64_RS_GR0;
1494 else if (strcmp (name, "CFM") == 0)
1495 return IA64_RS_CFM;
1496 else if (strcmp (name, "PR63") == 0)
1497 return IA64_RS_PR63;
1498 else if (strcmp (name, "RSE") == 0)
1499 return IA64_RS_RSE;
1500
1501 return IA64_RS_ANY;
1502}
1503
bde78a07 1504static void
800eeca4
JW
1505print_dependency_table ()
1506{
1507 int i, j;
1508
1509 if (debug)
1510 {
1511 for (i=0;i < iclen;i++)
1512 {
1513 if (ics[i]->is_class)
1514 {
1515 if (!ics[i]->nsubs)
1516 {
800eeca4 1517 if (ics[i]->comment)
bde78a07
NC
1518 warn (_("IC:%s [%s] has no terminals or sub-classes\n"),
1519 ics[i]->name, ics[i]->comment);
1520 else
1521 warn (_("IC:%s has no terminals or sub-classes\n"),
1522 ics[i]->name);
800eeca4
JW
1523 }
1524 }
1525 else
1526 {
1527 if (!ics[i]->terminal_resolved && !ics[i]->orphan)
1528 {
800eeca4 1529 if (ics[i]->comment)
bde78a07
NC
1530 warn (_("no insns mapped directly to terminal IC %s [%s]"),
1531 ics[i]->name, ics[i]->comment);
1532 else
1533 warn (_("no insns mapped directly to terminal IC %s\n"),
1534 ics[i]->name);
800eeca4
JW
1535 }
1536 }
1537 }
1538
bde78a07 1539 for (i = 0; i < iclen; i++)
800eeca4
JW
1540 {
1541 if (ics[i]->orphan)
1542 {
1543 mark_used (ics[i], 1);
bde78a07
NC
1544 warn (_("class %s is defined but not used\n"),
1545 ics[i]->name);
800eeca4
JW
1546 }
1547 }
1548
bde78a07
NC
1549 if (debug > 1)
1550 for (i = 0; i < rdepslen; i++)
1551 {
1552 static const char *mode_str[] = { "RAW", "WAW", "WAR" };
1553
1554 if (rdeps[i]->total_chks == 0)
168411b1
NC
1555 {
1556 if (rdeps[i]->total_regs)
7a53bcd4 1557 warn (_("Warning: rsrc %s (%s) has no chks\n"),
168411b1
NC
1558 rdeps[i]->name, mode_str[rdeps[i]->mode]);
1559 else
1560 warn (_("Warning: rsrc %s (%s) has no chks or regs\n"),
1561 rdeps[i]->name, mode_str[rdeps[i]->mode]);
1562 }
bde78a07
NC
1563 else if (rdeps[i]->total_regs == 0)
1564 warn (_("rsrc %s (%s) has no regs\n"),
1565 rdeps[i]->name, mode_str[rdeps[i]->mode]);
1566 }
800eeca4
JW
1567 }
1568
bde78a07 1569 /* The dependencies themselves. */
800eeca4 1570 printf ("static const struct ia64_dependency\ndependencies[] = {\n");
bde78a07 1571 for (i = 0; i < rdepslen; i++)
800eeca4
JW
1572 {
1573 /* '%', '#', AR[], CR[], or PSR. indicates we need to specify the actual
bde78a07 1574 resource used. */
800eeca4
JW
1575 int specifier = lookup_specifier (rdeps[i]->name);
1576 int regindex = lookup_regindex (rdeps[i]->name, specifier);
1577
1578 printf (" { \"%s\", %d, %d, %d, %d, ",
1579 rdeps[i]->name, specifier,
1580 (int)rdeps[i]->mode, (int)rdeps[i]->semantics, regindex);
1581 if (rdeps[i]->semantics == IA64_DVS_OTHER)
7f3dfb9c
L
1582 {
1583 const char *quote, *rest;
1584
1585 putchar ('\"');
1586 rest = rdeps[i]->extra;
1587 quote = strchr (rest, '\"');
1588 while (quote != NULL)
1589 {
1590 printf ("%.*s\\\"", (int) (quote - rest), rest);
1591 rest = quote + 1;
1592 quote = strchr (rest, '\"');
1593 }
1594 printf ("%s\", ", rest);
1595 }
514829c3
JW
1596 else
1597 printf ("NULL, ");
800eeca4
JW
1598 printf("},\n");
1599 }
1600 printf ("};\n\n");
1601
bde78a07 1602 /* And dependency lists. */
800eeca4
JW
1603 for (i=0;i < dlistlen;i++)
1604 {
1605 int len = 2;
53c9ebc5 1606 printf ("static const unsigned short dep%d[] = {\n ", i);
800eeca4
JW
1607 for (j=0;j < dlists[i]->len; j++)
1608 {
1609 len += printf ("%d, ", dlists[i]->deps[j]);
1610 if (len > 75)
1611 {
1612 printf("\n ");
1613 len = 2;
1614 }
1615 }
1616 printf ("\n};\n\n");
1617 }
1618
bde78a07 1619 /* And opcode dependency list. */
800eeca4
JW
1620 printf ("#define NELS(X) (sizeof(X)/sizeof(X[0]))\n");
1621 printf ("static const struct ia64_opcode_dependency\n");
1622 printf ("op_dependencies[] = {\n");
bde78a07 1623 for (i = 0; i < opdeplen; i++)
800eeca4
JW
1624 {
1625 printf (" { ");
1626 if (opdeps[i]->chk == -1)
1627 printf ("0, NULL, ");
1628 else
1629 printf ("NELS(dep%d), dep%d, ", opdeps[i]->chk, opdeps[i]->chk);
1630 if (opdeps[i]->reg == -1)
1631 printf ("0, NULL, ");
1632 else
1633 printf ("NELS(dep%d), dep%d, ", opdeps[i]->reg, opdeps[i]->reg);
1634 printf ("},\n");
1635 }
1636 printf ("};\n\n");
1637}
1638
1639\f
bde78a07 1640/* Add STR to the string table. */
800eeca4 1641static struct string_entry *
bde78a07 1642insert_string (char *str)
800eeca4
JW
1643{
1644 int start = 0, end = strtablen;
1645 int i, x;
1646
1647 if (strtablen == strtabtotlen)
1648 {
1649 strtabtotlen += 20;
1650 string_table = (struct string_entry **)
1651 xrealloc (string_table,
1652 sizeof (struct string_entry **) * strtabtotlen);
1653 }
1654
1655 if (strtablen == 0)
1656 {
1657 strtablen = 1;
1658 string_table[0] = tmalloc (struct string_entry);
1659 string_table[0]->s = xstrdup (str);
1660 string_table[0]->num = 0;
1661 return string_table[0];
1662 }
1663
1664 if (strcmp (str, string_table[strtablen - 1]->s) > 0)
bde78a07 1665 i = end;
800eeca4 1666 else if (strcmp (str, string_table[0]->s) < 0)
bde78a07 1667 i = 0;
800eeca4
JW
1668 else
1669 {
1670 while (1)
1671 {
1672 int c;
1673
1674 i = (start + end) / 2;
1675 c = strcmp (str, string_table[i]->s);
bde78a07 1676
800eeca4 1677 if (c < 0)
bde78a07 1678 end = i - 1;
800eeca4 1679 else if (c == 0)
bde78a07 1680 return string_table[i];
800eeca4 1681 else
bde78a07
NC
1682 start = i + 1;
1683
800eeca4 1684 if (start > end)
bde78a07 1685 break;
800eeca4
JW
1686 }
1687 }
bde78a07 1688
800eeca4 1689 for (; i > 0 && i < strtablen; i--)
bde78a07
NC
1690 if (strcmp (str, string_table[i - 1]->s) > 0)
1691 break;
1692
800eeca4 1693 for (; i < strtablen; i++)
bde78a07
NC
1694 if (strcmp (str, string_table[i]->s) < 0)
1695 break;
1696
800eeca4
JW
1697 for (x = strtablen - 1; x >= i; x--)
1698 {
1699 string_table[x + 1] = string_table[x];
1700 string_table[x + 1]->num = x + 1;
1701 }
bde78a07 1702
800eeca4
JW
1703 string_table[i] = tmalloc (struct string_entry);
1704 string_table[i]->s = xstrdup (str);
1705 string_table[i]->num = i;
1706 strtablen++;
bde78a07 1707
800eeca4
JW
1708 return string_table[i];
1709}
1710\f
bde78a07
NC
1711static struct bittree *
1712make_bittree_entry (void)
800eeca4
JW
1713{
1714 struct bittree *res = tmalloc (struct bittree);
1715
1716 res->disent = NULL;
1717 res->bits[0] = NULL;
1718 res->bits[1] = NULL;
1719 res->bits[2] = NULL;
1720 res->skip_flag = 0;
1721 res->bits_to_skip = 0;
1722 return res;
1723}
bde78a07 1724
800eeca4 1725\f
bde78a07 1726static struct disent *
aa170a07 1727add_dis_table_ent (which, insn, order, completer_index)
800eeca4
JW
1728 struct disent *which;
1729 int insn;
aa170a07 1730 int order;
800eeca4
JW
1731 int completer_index;
1732{
1733 int ci = 0;
1734 struct disent *ent;
1735
1736 if (which != NULL)
1737 {
1738 ent = which;
1739
1740 ent->nextcnt++;
1741 while (ent->nexte != NULL)
bde78a07
NC
1742 ent = ent->nexte;
1743
800eeca4
JW
1744 ent = (ent->nexte = tmalloc (struct disent));
1745 }
1746 else
1747 {
1748 ent = tmalloc (struct disent);
1749 ent->next_ent = disinsntable;
1750 disinsntable = ent;
1751 which = ent;
1752 }
1753 ent->nextcnt = 0;
1754 ent->nexte = NULL;
1755 ent->insn = insn;
aa170a07
TW
1756 ent->priority = order;
1757
800eeca4
JW
1758 while (completer_index != 1)
1759 {
1760 ci = (ci << 1) | (completer_index & 1);
1761 completer_index >>= 1;
1762 }
1763 ent->completer_index = ci;
1764 return which;
1765}
1766\f
bde78a07 1767static void
800eeca4
JW
1768finish_distable ()
1769{
1770 struct disent *ent = disinsntable;
1771 struct disent *prev = ent;
1772
1773 ent->ournum = 32768;
1774 while ((ent = ent->next_ent) != NULL)
1775 {
1776 ent->ournum = prev->ournum + prev->nextcnt + 1;
1777 prev = ent;
1778 }
1779}
1780\f
bde78a07 1781static void
aa170a07
TW
1782insert_bit_table_ent (curr_ent, bit, opcode, mask,
1783 opcodenum, order, completer_index)
800eeca4
JW
1784 struct bittree *curr_ent;
1785 int bit;
1786 ia64_insn opcode;
1787 ia64_insn mask;
1788 int opcodenum;
aa170a07 1789 int order;
800eeca4
JW
1790 int completer_index;
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
800eeca4 1823add_dis_entry (first, opcode, mask, opcodenum, ent, completer_index)
aa170a07 1824 struct bittree *first;
800eeca4
JW
1825 ia64_insn opcode;
1826 ia64_insn mask;
1827 int opcodenum;
1828 struct completer_entry *ent;
1829 int completer_index;
1830{
1831 if (completer_index & (1 << 20))
bde78a07 1832 abort ();
c1485d85 1833
800eeca4
JW
1834 while (ent != NULL)
1835 {
1836 ia64_insn newopcode = (opcode & (~ ent->mask)) | ent->bits;
1837 add_dis_entry (first, newopcode, mask, opcodenum, ent->addl_entries,
1838 (completer_index << 1) | 1);
bde78a07 1839
800eeca4
JW
1840 if (ent->is_terminal)
1841 {
aa170a07
TW
1842 insert_bit_table_ent (bittree, 40, newopcode, mask,
1843 opcodenum, opcode_count - ent->order - 1,
800eeca4
JW
1844 (completer_index << 1) | 1);
1845 }
1846 completer_index <<= 1;
1847 ent = ent->alternative;
1848 }
1849}
1850\f
bde78a07
NC
1851/* This optimization pass combines multiple "don't care" nodes. */
1852static void
800eeca4
JW
1853compact_distree (ent)
1854 struct bittree *ent;
1855{
1856#define IS_SKIP(ent) \
1857 ((ent->bits[2] !=NULL) \
1858 && (ent->bits[0] == NULL && ent->bits[1] == NULL && ent->skip_flag == 0))
1859
1860 int bitcnt = 0;
1861 struct bittree *nent = ent;
1862 int x;
1863
1864 while (IS_SKIP (nent))
1865 {
1866 bitcnt++;
1867 nent = nent->bits[2];
1868 }
1869
1870 if (bitcnt)
1871 {
1872 struct bittree *next = ent->bits[2];
1873
1874 ent->bits[0] = nent->bits[0];
1875 ent->bits[1] = nent->bits[1];
1876 ent->bits[2] = nent->bits[2];
1877 ent->disent = nent->disent;
1878 ent->skip_flag = 1;
1879 ent->bits_to_skip = bitcnt;
1880 while (next != nent)
1881 {
1882 struct bittree *b = next;
1883 next = next->bits[2];
1884 free (b);
1885 }
1886 free (nent);
1887 }
1888
1889 for (x = 0; x < 3; x++)
1890 {
1891 struct bittree *i = ent->bits[x];
bde78a07 1892
800eeca4 1893 if (i != NULL)
bde78a07 1894 compact_distree (i);
800eeca4
JW
1895 }
1896}
1897\f
1898static unsigned char *insn_list;
1899static int insn_list_len = 0;
1900static int tot_insn_list_len = 0;
1901
1902/* Generate the disassembler state machine corresponding to the tree
1903 in ENT. */
bde78a07 1904static void
800eeca4
JW
1905gen_dis_table (ent)
1906 struct bittree *ent;
1907{
1908 int x;
1909 int our_offset = insn_list_len;
1910 int bitsused = 5;
1911 int totbits = bitsused;
1912 int needed_bytes;
1913 int zero_count = 0;
bde78a07 1914 int zero_dest = 0; /* Initialize this with 0 to keep gcc quiet... */
800eeca4
JW
1915
1916 /* If this is a terminal entry, there's no point in skipping any
bde78a07 1917 bits. */
800eeca4
JW
1918 if (ent->skip_flag && ent->bits[0] == NULL && ent->bits[1] == NULL &&
1919 ent->bits[2] == NULL)
1920 {
1921 if (ent->disent == NULL)
bde78a07 1922 abort ();
800eeca4 1923 else
bde78a07 1924 ent->skip_flag = 0;
800eeca4
JW
1925 }
1926
1927 /* Calculate the amount of space needed for this entry, or at least
bde78a07 1928 a conservatively large approximation. */
800eeca4 1929 if (ent->skip_flag)
bde78a07
NC
1930 totbits += 5;
1931
800eeca4 1932 for (x = 1; x < 3; x++)
bde78a07
NC
1933 if (ent->bits[x] != NULL)
1934 totbits += 16;
800eeca4
JW
1935
1936 if (ent->disent != NULL)
1937 {
1938 if (ent->bits[2] != NULL)
bde78a07
NC
1939 abort ();
1940
800eeca4
JW
1941 totbits += 16;
1942 }
1943
bde78a07 1944 /* Now allocate the space. */
800eeca4
JW
1945 needed_bytes = (totbits + 7) / 8;
1946 if ((needed_bytes + insn_list_len) > tot_insn_list_len)
1947 {
1948 tot_insn_list_len += 256;
53c9ebc5 1949 insn_list = (unsigned char *) xrealloc (insn_list, tot_insn_list_len);
800eeca4
JW
1950 }
1951 our_offset = insn_list_len;
1952 insn_list_len += needed_bytes;
1953 memset (insn_list + our_offset, 0, needed_bytes);
1954
1955 /* Encode the skip entry by setting bit 6 set in the state op field,
bde78a07 1956 and store the # of bits to skip immediately after. */
800eeca4
JW
1957 if (ent->skip_flag)
1958 {
1959 bitsused += 5;
1960 insn_list[our_offset + 0] |= 0x40 | ((ent->bits_to_skip >> 2) & 0xf);
1961 insn_list[our_offset + 1] |= ((ent->bits_to_skip & 3) << 6);
1962 }
1963
1964#define IS_ONLY_IFZERO(ENT) \
1965 ((ENT)->bits[0] != NULL && (ENT)->bits[1] == NULL && (ENT)->bits[2] == NULL \
1966 && (ENT)->disent == NULL && (ENT)->skip_flag == 0)
1967
1968 /* Store an "if (bit is zero)" instruction by setting bit 7 in the
bde78a07 1969 state op field. */
800eeca4
JW
1970 if (ent->bits[0] != NULL)
1971 {
1972 struct bittree *nent = ent->bits[0];
1973 zero_count = 0;
1974
1975 insn_list[our_offset] |= 0x80;
1976
1977 /* We can encode sequences of multiple "if (bit is zero)" tests
1978 by storing the # of zero bits to check in the lower 3 bits of
1979 the instruction. However, this only applies if the state
1980 solely tests for a zero bit. */
1981
1982 if (IS_ONLY_IFZERO (ent))
1983 {
1984 while (IS_ONLY_IFZERO (nent) && zero_count < 7)
1985 {
1986 nent = nent->bits[0];
1987 zero_count++;
1988 }
1989
1990 insn_list[our_offset + 0] |= zero_count;
1991 }
1992 zero_dest = insn_list_len;
1993 gen_dis_table (nent);
1994 }
1995
1996 /* Now store the remaining tests. We also handle a sole "termination
1997 entry" by storing it as an "any bit" test. */
1998
1999 for (x = 1; x < 3; x++)
2000 {
2001 if (ent->bits[x] != NULL || (x == 2 && ent->disent != NULL))
2002 {
2003 struct bittree *i = ent->bits[x];
2004 int idest;
2005 int currbits = 15;
2006
2007 if (i != NULL)
2008 {
2009 /* If the instruction being branched to only consists of
2010 a termination entry, use the termination entry as the
2011 place to branch to instead. */
2012 if (i->bits[0] == NULL && i->bits[1] == NULL
2013 && i->bits[2] == NULL && i->disent != NULL)
2014 {
2015 idest = i->disent->ournum;
2016 i = NULL;
2017 }
2018 else
bde78a07 2019 idest = insn_list_len - our_offset;
800eeca4
JW
2020 }
2021 else
bde78a07 2022 idest = ent->disent->ournum;
800eeca4
JW
2023
2024 /* If the destination offset for the if (bit is 1) test is less
2025 than 256 bytes away, we can store it as 8-bits instead of 16;
2026 the instruction has bit 5 set for the 16-bit address, and bit
2027 4 for the 8-bit address. Since we've already allocated 16
2028 bits for the address we need to deallocate the space.
2029
2030 Note that branchings within the table are relative, and
2031 there are no branches that branch past our instruction yet
bde78a07 2032 so we do not need to adjust any other offsets. */
800eeca4
JW
2033 if (x == 1)
2034 {
2035 if (idest <= 256)
2036 {
2037 int start = our_offset + bitsused / 8 + 1;
2038
2039 memmove (insn_list + start,
2040 insn_list + start + 1,
2041 insn_list_len - (start + 1));
2042 currbits = 7;
2043 totbits -= 8;
2044 needed_bytes--;
2045 insn_list_len--;
2046 insn_list[our_offset] |= 0x10;
2047 idest--;
2048 }
2049 else
bde78a07 2050 insn_list[our_offset] |= 0x20;
800eeca4
JW
2051 }
2052 else
2053 {
2054 /* An instruction which solely consists of a termination
2055 marker and whose disassembly name index is < 4096
2056 can be stored in 16 bits. The encoding is slightly
2057 odd; the upper 4 bits of the instruction are 0x3, and
2058 bit 3 loses its normal meaning. */
2059
2060 if (ent->bits[0] == NULL && ent->bits[1] == NULL
2061 && ent->bits[2] == NULL && ent->skip_flag == 0
2062 && ent->disent != NULL
2063 && ent->disent->ournum < (32768 + 4096))
2064 {
2065 int start = our_offset + bitsused / 8 + 1;
2066
2067 memmove (insn_list + start,
2068 insn_list + start + 1,
2069 insn_list_len - (start + 1));
2070 currbits = 11;
2071 totbits -= 5;
2072 bitsused--;
2073 needed_bytes--;
2074 insn_list_len--;
2075 insn_list[our_offset] |= 0x30;
2076 idest &= ~32768;
2077 }
2078 else
bde78a07 2079 insn_list[our_offset] |= 0x08;
800eeca4 2080 }
bde78a07 2081
800eeca4
JW
2082 if (debug)
2083 {
2084 int id = idest;
2085
2086 if (i == NULL)
bde78a07 2087 id |= 32768;
800eeca4 2088 else if (! (id & 32768))
bde78a07
NC
2089 id += our_offset;
2090
800eeca4 2091 if (x == 1)
bde78a07 2092 printf ("%d: if (1) goto %d\n", our_offset, id);
800eeca4 2093 else
bde78a07 2094 printf ("%d: try %d\n", our_offset, id);
800eeca4
JW
2095 }
2096
bde78a07 2097 /* Store the address of the entry being branched to. */
800eeca4
JW
2098 while (currbits >= 0)
2099 {
53c9ebc5 2100 unsigned char *byte = insn_list + our_offset + bitsused / 8;
800eeca4
JW
2101
2102 if (idest & (1 << currbits))
bde78a07
NC
2103 *byte |= (1 << (7 - (bitsused % 8)));
2104
800eeca4
JW
2105 bitsused++;
2106 currbits--;
2107 }
2108
bde78a07 2109 /* Now generate the states for the entry being branched to. */
800eeca4 2110 if (i != NULL)
bde78a07 2111 gen_dis_table (i);
800eeca4
JW
2112 }
2113 }
bde78a07 2114
800eeca4
JW
2115 if (debug)
2116 {
2117 if (ent->skip_flag)
bde78a07 2118 printf ("%d: skipping %d\n", our_offset, ent->bits_to_skip);
800eeca4
JW
2119
2120 if (ent->bits[0] != NULL)
bde78a07
NC
2121 printf ("%d: if (0:%d) goto %d\n", our_offset, zero_count + 1,
2122 zero_dest);
800eeca4 2123 }
bde78a07 2124
800eeca4 2125 if (bitsused != totbits)
bde78a07 2126 abort ();
800eeca4
JW
2127}
2128\f
bde78a07
NC
2129static void
2130print_dis_table (void)
800eeca4
JW
2131{
2132 int x;
2133 struct disent *cent = disinsntable;
2134
2135 printf ("static const char dis_table[] = {\n");
2136 for (x = 0; x < insn_list_len; x++)
2137 {
2138 if ((x > 0) && ((x % 12) == 0))
bde78a07
NC
2139 printf ("\n");
2140
800eeca4
JW
2141 printf ("0x%02x, ", insn_list[x]);
2142 }
2143 printf ("\n};\n\n");
2144
2145 printf ("static const struct ia64_dis_names ia64_dis_names[] = {\n");
2146 while (cent != NULL)
2147 {
2148 struct disent *ent = cent;
2149
2150 while (ent != NULL)
2151 {
aa170a07
TW
2152 printf ("{ 0x%x, %d, %d, %d },\n", ent->completer_index,
2153 ent->insn, (ent->nexte != NULL ? 1 : 0),
2154 ent->priority);
800eeca4
JW
2155 ent = ent->nexte;
2156 }
2157 cent = cent->next_ent;
2158 }
2159 printf ("};\n\n");
2160}
2161\f
bde78a07
NC
2162static void
2163generate_disassembler (void)
800eeca4 2164{
aa170a07 2165 int i;
800eeca4
JW
2166
2167 bittree = make_bittree_entry ();
2168
bde78a07 2169 for (i = 0; i < otlen; i++)
800eeca4 2170 {
aa170a07
TW
2171 struct main_entry *ptr = ordered_table[i];
2172
800eeca4 2173 if (ptr->opcode->type != IA64_TYPE_DYN)
bde78a07
NC
2174 add_dis_entry (bittree,
2175 ptr->opcode->opcode, ptr->opcode->mask,
2176 ptr->main_index,
2177 ptr->completers, 1);
800eeca4
JW
2178 }
2179
2180 compact_distree (bittree);
2181 finish_distable ();
2182 gen_dis_table (bittree);
2183
2184 print_dis_table ();
2185}
2186\f
bde78a07
NC
2187static void
2188print_string_table (void)
800eeca4
JW
2189{
2190 int x;
2191 char lbuf[80], buf[80];
2192 int blen = 0;
2193
bde78a07 2194 printf ("static const char * const ia64_strings[] = {\n");
800eeca4 2195 lbuf[0] = '\0';
bde78a07 2196
800eeca4
JW
2197 for (x = 0; x < strtablen; x++)
2198 {
2199 int len;
2200
2201 if (strlen (string_table[x]->s) > 75)
bde78a07
NC
2202 abort ();
2203
800eeca4
JW
2204 sprintf (buf, " \"%s\",", string_table[x]->s);
2205 len = strlen (buf);
bde78a07 2206
800eeca4
JW
2207 if ((blen + len) > 75)
2208 {
2209 printf (" %s\n", lbuf);
2210 lbuf[0] = '\0';
2211 blen = 0;
2212 }
2213 strcat (lbuf, buf);
2214 blen += len;
2215 }
bde78a07 2216
800eeca4 2217 if (blen > 0)
bde78a07
NC
2218 printf (" %s\n", lbuf);
2219
800eeca4
JW
2220 printf ("};\n\n");
2221}
2222\f
2223static struct completer_entry **glist;
2224static int glistlen = 0;
2225static int glisttotlen = 0;
2226
bde78a07 2227/* If the completer trees ENT1 and ENT2 are equal, return 1. */
800eeca4 2228
bde78a07 2229static int
800eeca4
JW
2230completer_entries_eq (ent1, ent2)
2231 struct completer_entry *ent1, *ent2;
2232{
2233 while (ent1 != NULL && ent2 != NULL)
2234 {
2235 if (ent1->name->num != ent2->name->num
2236 || ent1->bits != ent2->bits
2237 || ent1->mask != ent2->mask
2238 || ent1->is_terminal != ent2->is_terminal
aa170a07
TW
2239 || ent1->dependencies != ent2->dependencies
2240 || ent1->order != ent2->order)
bde78a07
NC
2241 return 0;
2242
800eeca4 2243 if (! completer_entries_eq (ent1->addl_entries, ent2->addl_entries))
bde78a07
NC
2244 return 0;
2245
800eeca4
JW
2246 ent1 = ent1->alternative;
2247 ent2 = ent2->alternative;
2248 }
bde78a07 2249
800eeca4
JW
2250 return ent1 == ent2;
2251}
2252\f
2253/* Insert ENT into the global list of completers and return it. If an
2254 equivalent entry (according to completer_entries_eq) already exists,
bde78a07
NC
2255 it is returned instead. */
2256static struct completer_entry *
2257insert_gclist (struct completer_entry *ent)
800eeca4
JW
2258{
2259 if (ent != NULL)
2260 {
2261 int i;
2262 int x;
2263 int start = 0, end;
2264
2265 ent->addl_entries = insert_gclist (ent->addl_entries);
2266 ent->alternative = insert_gclist (ent->alternative);
2267
2268 i = glistlen / 2;
2269 end = glistlen;
2270
2271 if (glisttotlen == glistlen)
2272 {
2273 glisttotlen += 20;
2274 glist = (struct completer_entry **)
2275 xrealloc (glist, sizeof (struct completer_entry *) * glisttotlen);
2276 }
2277
2278 if (glistlen == 0)
2279 {
2280 glist[0] = ent;
2281 glistlen = 1;
2282 return ent;
2283 }
2284
2285 if (ent->name->num < glist[0]->name->num)
bde78a07 2286 i = 0;
800eeca4 2287 else if (ent->name->num > glist[end - 1]->name->num)
bde78a07 2288 i = end;
800eeca4
JW
2289 else
2290 {
2291 int c;
2292
2293 while (1)
2294 {
2295 i = (start + end) / 2;
2296 c = ent->name->num - glist[i]->name->num;
bde78a07 2297
800eeca4 2298 if (c < 0)
bde78a07 2299 end = i - 1;
800eeca4
JW
2300 else if (c == 0)
2301 {
2302 while (i > 0
2303 && ent->name->num == glist[i - 1]->name->num)
bde78a07
NC
2304 i--;
2305
800eeca4
JW
2306 break;
2307 }
2308 else
bde78a07
NC
2309 start = i + 1;
2310
800eeca4 2311 if (start > end)
bde78a07 2312 break;
800eeca4 2313 }
bde78a07 2314
800eeca4
JW
2315 if (c == 0)
2316 {
2317 while (i < glistlen)
2318 {
2319 if (ent->name->num != glist[i]->name->num)
bde78a07
NC
2320 break;
2321
800eeca4 2322 if (completer_entries_eq (ent, glist[i]))
bde78a07
NC
2323 return glist[i];
2324
800eeca4
JW
2325 i++;
2326 }
2327 }
2328 }
bde78a07 2329
800eeca4 2330 for (; i > 0 && i < glistlen; i--)
bde78a07
NC
2331 if (ent->name->num >= glist[i - 1]->name->num)
2332 break;
2333
800eeca4 2334 for (; i < glistlen; i++)
bde78a07
NC
2335 if (ent->name->num < glist[i]->name->num)
2336 break;
2337
800eeca4 2338 for (x = glistlen - 1; x >= i; x--)
bde78a07
NC
2339 glist[x + 1] = glist[x];
2340
800eeca4
JW
2341 glist[i] = ent;
2342 glistlen++;
2343 }
2344 return ent;
2345}
2346\f
2347static int
2348get_prefix_len (name)
2349 const char *name;
2350{
2351 char *c;
2352
2353 if (name[0] == '\0')
bde78a07 2354 return 0;
800eeca4
JW
2355
2356 c = strchr (name, '.');
2357 if (c != NULL)
bde78a07 2358 return c - name;
800eeca4 2359 else
bde78a07 2360 return strlen (name);
800eeca4
JW
2361}
2362\f
2363static void
2364compute_completer_bits (ment, ent)
2365 struct main_entry *ment;
2366 struct completer_entry *ent;
2367{
2368 while (ent != NULL)
2369 {
2370 compute_completer_bits (ment, ent->addl_entries);
2371
2372 if (ent->is_terminal)
2373 {
2374 ia64_insn mask = 0;
2375 ia64_insn our_bits = ent->bits;
2376 struct completer_entry *p = ent->parent;
2377 ia64_insn p_bits;
2378 int x;
2379
2380 while (p != NULL && ! p->is_terminal)
bde78a07 2381 p = p->parent;
800eeca4
JW
2382
2383 if (p != NULL)
bde78a07 2384 p_bits = p->bits;
800eeca4 2385 else
bde78a07 2386 p_bits = ment->opcode->opcode;
800eeca4
JW
2387
2388 for (x = 0; x < 64; x++)
2389 {
2390 ia64_insn m = ((ia64_insn) 1) << x;
bde78a07 2391
800eeca4 2392 if ((p_bits & m) != (our_bits & m))
bde78a07 2393 mask |= m;
800eeca4 2394 else
bde78a07 2395 our_bits &= ~m;
800eeca4
JW
2396 }
2397 ent->bits = our_bits;
2398 ent->mask = mask;
2399 }
2400 else
2401 {
2402 ent->bits = 0;
2403 ent->mask = 0;
2404 }
2405
2406 ent = ent->alternative;
2407 }
2408}
2409\f
2410/* Find identical completer trees that are used in different
bde78a07
NC
2411 instructions and collapse their entries. */
2412static void
2413collapse_redundant_completers (void)
800eeca4
JW
2414{
2415 struct main_entry *ptr;
2416 int x;
2417
2418 for (ptr = maintable; ptr != NULL; ptr = ptr->next)
2419 {
2420 if (ptr->completers == NULL)
bde78a07
NC
2421 abort ();
2422
800eeca4
JW
2423 compute_completer_bits (ptr, ptr->completers);
2424 ptr->completers = insert_gclist (ptr->completers);
2425 }
2426
2427 /* The table has been finalized, now number the indexes. */
2428 for (x = 0; x < glistlen; x++)
bde78a07 2429 glist[x]->num = x;
800eeca4
JW
2430}
2431\f
2432
bde78a07 2433/* Attach two lists of dependencies to each opcode.
800eeca4
JW
2434 1) all resources which, when already marked in use, conflict with this
2435 opcode (chks)
2436 2) all resources which must be marked in use when this opcode is used
bde78a07
NC
2437 (regs). */
2438static int
800eeca4
JW
2439insert_opcode_dependencies (opc, cmp)
2440 struct ia64_opcode *opc;
514829c3 2441 struct completer_entry *cmp ATTRIBUTE_UNUSED;
800eeca4 2442{
bde78a07
NC
2443 /* Note all resources which point to this opcode. rfi has the most chks
2444 (79) and cmpxchng has the most regs (54) so 100 here should be enough. */
800eeca4
JW
2445 int i;
2446 int nregs = 0;
2447 unsigned short regs[256];
2448 int nchks = 0;
2449 unsigned short chks[256];
bde78a07 2450 /* Flag insns for which no class matched; there should be none. */
800eeca4
JW
2451 int no_class_found = 1;
2452
bde78a07 2453 for (i = 0; i < rdepslen; i++)
800eeca4
JW
2454 {
2455 struct rdep *rs = rdeps[i];
2456 int j;
2457
2458 if (strcmp (opc->name, "cmp.eq.and") == 0
0112cd26 2459 && CONST_STRNEQ (rs->name, "PR%")
800eeca4
JW
2460 && rs->mode == 1)
2461 no_class_found = 99;
2462
2463 for (j=0; j < rs->nregs;j++)
2464 {
2465 int ic_note = 0;
2466
2467 if (in_iclass (opc, ics[rs->regs[j]], NULL, NULL, &ic_note))
2468 {
bde78a07 2469 /* We can ignore ic_note 11 for non PR resources. */
0112cd26 2470 if (ic_note == 11 && ! CONST_STRNEQ (rs->name, "PR"))
800eeca4
JW
2471 ic_note = 0;
2472
2473 if (ic_note != 0 && rs->regnotes[j] != 0
2474 && ic_note != rs->regnotes[j]
2475 && !(ic_note == 11 && rs->regnotes[j] == 1))
bde78a07
NC
2476 warn (_("IC note %d in opcode %s (IC:%s) conflicts with resource %s note %d\n"),
2477 ic_note, opc->name, ics[rs->regs[j]]->name,
2478 rs->name, rs->regnotes[j]);
800eeca4
JW
2479 /* Instruction class notes override resource notes.
2480 So far, only note 11 applies to an IC instead of a resource,
bde78a07 2481 and note 11 implies note 1. */
800eeca4
JW
2482 if (ic_note)
2483 regs[nregs++] = RDEP(ic_note, i);
2484 else
2485 regs[nregs++] = RDEP(rs->regnotes[j], i);
2486 no_class_found = 0;
2487 ++rs->total_regs;
2488 }
2489 }
bde78a07
NC
2490
2491 for (j = 0; j < rs->nchks; j++)
800eeca4
JW
2492 {
2493 int ic_note = 0;
2494
2495 if (in_iclass (opc, ics[rs->chks[j]], NULL, NULL, &ic_note))
2496 {
bde78a07 2497 /* We can ignore ic_note 11 for non PR resources. */
0112cd26 2498 if (ic_note == 11 && ! CONST_STRNEQ (rs->name, "PR"))
800eeca4
JW
2499 ic_note = 0;
2500
2501 if (ic_note != 0 && rs->chknotes[j] != 0
2502 && ic_note != rs->chknotes[j]
2503 && !(ic_note == 11 && rs->chknotes[j] == 1))
bde78a07
NC
2504 warn (_("IC note %d for opcode %s (IC:%s) conflicts with resource %s note %d\n"),
2505 ic_note, opc->name, ics[rs->chks[j]]->name,
2506 rs->name, rs->chknotes[j]);
800eeca4
JW
2507 if (ic_note)
2508 chks[nchks++] = RDEP(ic_note, i);
2509 else
2510 chks[nchks++] = RDEP(rs->chknotes[j], i);
2511 no_class_found = 0;
2512 ++rs->total_chks;
2513 }
2514 }
2515 }
2516
2517 if (no_class_found)
bde78a07
NC
2518 warn (_("opcode %s has no class (ops %d %d %d)\n"),
2519 opc->name,
2520 opc->operands[0], opc->operands[1], opc->operands[2]);
800eeca4
JW
2521
2522 return insert_dependencies (nchks, chks, nregs, regs);
2523}
2524\f
bde78a07 2525static void
aa170a07 2526insert_completer_entry (opc, tabent, order)
800eeca4
JW
2527 struct ia64_opcode *opc;
2528 struct main_entry *tabent;
aa170a07 2529 int order;
800eeca4
JW
2530{
2531 struct completer_entry **ptr = &tabent->completers;
2532 struct completer_entry *parent = NULL;
2533 char pcopy[129], *prefix;
2534 int at_end = 0;
2535
2536 if (strlen (opc->name) > 128)
bde78a07
NC
2537 abort ();
2538
800eeca4
JW
2539 strcpy (pcopy, opc->name);
2540 prefix = pcopy + get_prefix_len (pcopy);
bde78a07 2541
800eeca4 2542 if (prefix[0] != '\0')
bde78a07 2543 prefix++;
800eeca4
JW
2544
2545 while (! at_end)
2546 {
2547 int need_new_ent = 1;
2548 int plen = get_prefix_len (prefix);
2549 struct string_entry *sent;
2550
2551 at_end = (prefix[plen] == '\0');
2552 prefix[plen] = '\0';
2553 sent = insert_string (prefix);
2554
2555 while (*ptr != NULL)
2556 {
2557 int cmpres = sent->num - (*ptr)->name->num;
2558
2559 if (cmpres == 0)
2560 {
2561 need_new_ent = 0;
2562 break;
2563 }
800eeca4 2564 else
bde78a07 2565 ptr = &((*ptr)->alternative);
800eeca4 2566 }
bde78a07 2567
800eeca4
JW
2568 if (need_new_ent)
2569 {
2570 struct completer_entry *nent = tmalloc (struct completer_entry);
bde78a07 2571
800eeca4
JW
2572 nent->name = sent;
2573 nent->parent = parent;
2574 nent->addl_entries = NULL;
2575 nent->alternative = *ptr;
2576 *ptr = nent;
2577 nent->is_terminal = 0;
2578 nent->dependencies = -1;
2579 }
2580
2581 if (! at_end)
2582 {
2583 parent = *ptr;
2584 ptr = &((*ptr)->addl_entries);
2585 prefix += plen + 1;
2586 }
2587 }
2588
2589 if ((*ptr)->is_terminal)
bde78a07 2590 abort ();
800eeca4
JW
2591
2592 (*ptr)->is_terminal = 1;
2593 (*ptr)->mask = (ia64_insn)-1;
2594 (*ptr)->bits = opc->opcode;
800eeca4 2595 (*ptr)->dependencies = insert_opcode_dependencies (opc, *ptr);
aa170a07 2596 (*ptr)->order = order;
800eeca4
JW
2597}
2598\f
bde78a07 2599static void
800eeca4
JW
2600print_completer_entry (ent)
2601 struct completer_entry *ent;
2602{
2603 int moffset = 0;
2604 ia64_insn mask = ent->mask, bits = ent->bits;
2605
2606 if (mask != 0)
2607 {
2608 while (! (mask & 1))
2609 {
2610 moffset++;
2611 mask = mask >> 1;
2612 bits = bits >> 1;
2613 }
bde78a07 2614
800eeca4 2615 if (bits & 0xffffffff00000000LL)
bde78a07 2616 abort ();
800eeca4
JW
2617 }
2618
2619 printf (" { 0x%x, 0x%x, %d, %d, %d, %d, %d, %d },\n",
2620 (int)bits,
2621 (int)mask,
2622 ent->name->num,
2623 ent->alternative != NULL ? ent->alternative->num : -1,
2624 ent->addl_entries != NULL ? ent->addl_entries->num : -1,
2625 moffset,
2626 ent->is_terminal ? 1 : 0,
2627 ent->dependencies);
2628}
2629\f
bde78a07 2630static void
800eeca4
JW
2631print_completer_table ()
2632{
2633 int x;
2634
2635 printf ("static const struct ia64_completer_table\ncompleter_table[] = {\n");
2636 for (x = 0; x < glistlen; x++)
bde78a07 2637 print_completer_entry (glist[x]);
800eeca4
JW
2638 printf ("};\n\n");
2639}
2640\f
bde78a07 2641static int
800eeca4
JW
2642opcodes_eq (opc1, opc2)
2643 struct ia64_opcode *opc1;
2644 struct ia64_opcode *opc2;
2645{
2646 int x;
2647 int plen1, plen2;
2648
2649 if ((opc1->mask != opc2->mask) || (opc1->type != opc2->type)
2650 || (opc1->num_outputs != opc2->num_outputs)
2651 || (opc1->flags != opc2->flags))
bde78a07
NC
2652 return 0;
2653
800eeca4 2654 for (x = 0; x < 5; x++)
bde78a07
NC
2655 if (opc1->operands[x] != opc2->operands[x])
2656 return 0;
2657
800eeca4
JW
2658 plen1 = get_prefix_len (opc1->name);
2659 plen2 = get_prefix_len (opc2->name);
bde78a07 2660
800eeca4 2661 if (plen1 == plen2 && (memcmp (opc1->name, opc2->name, plen1) == 0))
bde78a07
NC
2662 return 1;
2663
800eeca4
JW
2664 return 0;
2665}
2666\f
bde78a07 2667static void
800eeca4
JW
2668add_opcode_entry (opc)
2669 struct ia64_opcode *opc;
2670{
2671 struct main_entry **place;
2672 struct string_entry *name;
2673 char prefix[129];
2674 int found_it = 0;
2675
2676 if (strlen (opc->name) > 128)
bde78a07
NC
2677 abort ();
2678
800eeca4
JW
2679 place = &maintable;
2680 strcpy (prefix, opc->name);
2681 prefix[get_prefix_len (prefix)] = '\0';
2682 name = insert_string (prefix);
2683
2684 /* Walk the list of opcode table entries. If it's a new
aa170a07 2685 instruction, allocate and fill in a new entry. Note
bde78a07 2686 the main table is alphabetical by opcode name. */
800eeca4
JW
2687
2688 while (*place != NULL)
2689 {
2690 if ((*place)->name->num == name->num
2691 && opcodes_eq ((*place)->opcode, opc))
2692 {
2693 found_it = 1;
2694 break;
2695 }
2696 if ((*place)->name->num > name->num)
bde78a07
NC
2697 break;
2698
800eeca4
JW
2699 place = &((*place)->next);
2700 }
2701 if (! found_it)
2702 {
2703 struct main_entry *nent = tmalloc (struct main_entry);
2704
2705 nent->name = name;
2706 nent->opcode = opc;
2707 nent->next = *place;
2708 nent->completers = 0;
2709 *place = nent;
aa170a07
TW
2710
2711 if (otlen == ottotlen)
2712 {
2713 ottotlen += 20;
2714 ordered_table = (struct main_entry **)
2715 xrealloc (ordered_table, sizeof (struct main_entry *) * ottotlen);
2716 }
2717 ordered_table[otlen++] = nent;
800eeca4 2718 }
c1485d85 2719
aa170a07 2720 insert_completer_entry (opc, *place, opcode_count++);
800eeca4
JW
2721}
2722\f
bde78a07
NC
2723static void
2724print_main_table (void)
800eeca4
JW
2725{
2726 struct main_entry *ptr = maintable;
aa170a07 2727 int index = 0;
800eeca4
JW
2728
2729 printf ("static const struct ia64_main_table\nmain_table[] = {\n");
2730 while (ptr != NULL)
2731 {
514829c3 2732 printf (" { %d, %d, %d, 0x",
800eeca4
JW
2733 ptr->name->num,
2734 ptr->opcode->type,
514829c3 2735 ptr->opcode->num_outputs);
aa2273ba 2736 opcode_fprintf_vma (stdout, ptr->opcode->opcode);
514829c3 2737 printf ("ull, 0x");
aa2273ba 2738 opcode_fprintf_vma (stdout, ptr->opcode->mask);
514829c3 2739 printf ("ull, { %d, %d, %d, %d, %d }, 0x%x, %d, },\n",
800eeca4
JW
2740 ptr->opcode->operands[0],
2741 ptr->opcode->operands[1],
2742 ptr->opcode->operands[2],
2743 ptr->opcode->operands[3],
2744 ptr->opcode->operands[4],
2745 ptr->opcode->flags,
2746 ptr->completers->num);
2747
aa170a07
TW
2748 ptr->main_index = index++;
2749
800eeca4
JW
2750 ptr = ptr->next;
2751 }
2752 printf ("};\n\n");
2753}
2754\f
bde78a07 2755static void
800eeca4
JW
2756shrink (table)
2757 struct ia64_opcode *table;
2758{
2759 int curr_opcode;
2760
2761 for (curr_opcode = 0; table[curr_opcode].name != NULL; curr_opcode++)
60b9a617
JB
2762 {
2763 add_opcode_entry (table + curr_opcode);
2764 if (table[curr_opcode].num_outputs == 2
2765 && ((table[curr_opcode].operands[0] == IA64_OPND_P1
2766 && table[curr_opcode].operands[1] == IA64_OPND_P2)
2767 || (table[curr_opcode].operands[0] == IA64_OPND_P2
2768 && table[curr_opcode].operands[1] == IA64_OPND_P1)))
2769 {
2770 struct ia64_opcode *alias = tmalloc(struct ia64_opcode);
2771 unsigned i;
2772
2773 *alias = table[curr_opcode];
2774 for (i = 2; i < NELEMS (alias->operands); ++i)
2775 alias->operands[i - 1] = alias->operands[i];
2776 alias->operands[NELEMS (alias->operands) - 1] = IA64_OPND_NIL;
2777 --alias->num_outputs;
2778 alias->flags |= PSEUDO;
2779 add_opcode_entry (alias);
2780 }
2781 }
800eeca4
JW
2782}
2783\f
bde78a07
NC
2784
2785/* Program options. */
2786#define OPTION_SRCDIR 200
2787
2788struct option long_options[] =
2789{
2790 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
2791 {"debug", no_argument, NULL, 'd'},
2792 {"version", no_argument, NULL, 'V'},
2793 {"help", no_argument, NULL, 'h'},
2794 {0, no_argument, NULL, 0}
2795};
2796
2797static void
2798print_version (void)
2799{
2800 printf ("%s: version 1.0\n", program_name);
2801 xexit (0);
2802}
2803
2804static void
2805usage (FILE * stream, int status)
2806{
2807 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2808 program_name);
2809 xexit (status);
2810}
2811
800eeca4 2812int
bde78a07 2813main (int argc, char **argv)
800eeca4 2814{
bde78a07
NC
2815 extern int chdir (char *);
2816 char *srcdir = NULL;
2817 int c;
2818
2819 program_name = *argv;
2820 xmalloc_set_program_name (program_name);
2821
2822 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2823 switch (c)
2824 {
2825 case OPTION_SRCDIR:
2826 srcdir = optarg;
2827 break;
2828 case 'V':
2829 case 'v':
2830 print_version ();
2831 break;
2832 case 'd':
2833 debug = 1;
2834 break;
2835 case 'h':
2836 case '?':
2837 usage (stderr, 0);
2838 default:
2839 case 0:
2840 break;
2841 }
2842
2843 if (optind != argc)
2844 usage (stdout, 1);
2845
2846 if (srcdir != NULL)
2847 if (chdir (srcdir) != 0)
2848 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2849 srcdir, strerror (errno));
800eeca4 2850
bde78a07
NC
2851 load_insn_classes ();
2852 load_dependencies ();
800eeca4
JW
2853
2854 shrink (ia64_opcodes_a);
2855 shrink (ia64_opcodes_b);
2856 shrink (ia64_opcodes_f);
2857 shrink (ia64_opcodes_i);
2858 shrink (ia64_opcodes_m);
2859 shrink (ia64_opcodes_x);
2860 shrink (ia64_opcodes_d);
2861
2862 collapse_redundant_completers ();
2863
bde78a07 2864 printf ("/* This file is automatically generated by ia64-gen. Do not edit! */\n");
9b201bb5
NC
2865 printf ("/* Copyright 2007 Free Software Foundation, Inc.\n\
2866\n\
2867 This file is part of the GNU opcodes library.\n\
2868\n\
2869 This library is free software; you can redistribute it and/or modify\n\
2870 it under the terms of the GNU General Public License as published by\n\
2871 the Free Software Foundation; either version 3, or (at your option)\n\
2872 any later version.\n\
2873\n\
2874 It is distributed in the hope that it will be useful, but WITHOUT\n\
2875 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
2876 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
2877 License for more details.\n\
2878\n\
2879 You should have received a copy of the GNU General Public License\n\
2880 along with this program; see the file COPYING. If not, write to the\n\
2881 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA\n\
b8deab37 2882 02110-1301, USA. */\n");
9b201bb5 2883
800eeca4
JW
2884 print_string_table ();
2885 print_dependency_table ();
2886 print_completer_table ();
2887 print_main_table ();
2888
2889 generate_disassembler ();
2890
2891 exit (0);
2892}
This page took 0.506791 seconds and 4 git commands to generate.