source: trunk/src/binutils/opcodes/ia64-gen.c@ 106

Last change on this file since 106 was 10, checked in by bird, 22 years ago

Initial revision

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