ia64-gen.c revision 84865
184865Sobrien/* ia64-gen.c -- Generate a shrunk set of opcode tables 284865Sobrien Copyright 1999, 2000 Free Software Foundation, Inc. 384865Sobrien Written by Bob Manson, Cygnus Solutions, <manson@cygnus.com> 484865Sobrien 584865Sobrien This file is part of GDB, GAS, and the GNU binutils. 684865Sobrien 784865Sobrien GDB, GAS, and the GNU binutils are free software; you can redistribute 884865Sobrien them and/or modify them under the terms of the GNU General Public 984865Sobrien License as published by the Free Software Foundation; either version 1084865Sobrien 2, or (at your option) any later version. 1184865Sobrien 1284865Sobrien GDB, GAS, and the GNU binutils are distributed in the hope that they 1384865Sobrien will be useful, but WITHOUT ANY WARRANTY; without even the implied 1484865Sobrien warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 1584865Sobrien the GNU General Public License for more details. 1684865Sobrien 1784865Sobrien You should have received a copy of the GNU General Public License 1884865Sobrien along with this file; see the file COPYING. If not, write to the 1984865Sobrien Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2084865Sobrien 02111-1307, USA. */ 2184865Sobrien 2284865Sobrien/* While the ia64-opc-* set of opcode tables are easy to maintain, 2384865Sobrien they waste a tremendous amount of space. ia64-gen rearranges the 2484865Sobrien instructions into a directed acyclic graph (DAG) of instruction opcodes and 2584865Sobrien their possible completers, as well as compacting the set of strings used. 2684865Sobrien 2784865Sobrien The disassembler table consists of a state machine that does 2884865Sobrien branching based on the bits of the opcode being disassembled. The 2984865Sobrien state encodings have been chosen to minimize the amount of space 3084865Sobrien required. 3184865Sobrien 3284865Sobrien The resource table is constructed based on some text dependency tables, 3384865Sobrien which are also easier to maintain than the final representation. 3484865Sobrien 3584865Sobrien*/ 3684865Sobrien 3784865Sobrien#include <stdio.h> 3884865Sobrien#include <ctype.h> 3984865Sobrien 4084865Sobrien#include "ansidecl.h" 4184865Sobrien#include "libiberty.h" 4284865Sobrien#include "sysdep.h" 4384865Sobrien#include "ia64-opc.h" 4484865Sobrien#include "ia64-opc-a.c" 4584865Sobrien#include "ia64-opc-i.c" 4684865Sobrien#include "ia64-opc-m.c" 4784865Sobrien#include "ia64-opc-b.c" 4884865Sobrien#include "ia64-opc-f.c" 4984865Sobrien#include "ia64-opc-x.c" 5084865Sobrien#include "ia64-opc-d.c" 5184865Sobrien 5284865Sobrienint debug = 0; 5384865Sobrien 5484865Sobrien#define tmalloc(X) (X *) xmalloc (sizeof (X)) 5584865Sobrien 5684865Sobrien/* The main opcode table entry. Each entry is a unique combination of 5784865Sobrien name and flags (no two entries in the table compare as being equal 5884865Sobrien via opcodes_eq). */ 5984865Sobrienstruct main_entry 6084865Sobrien{ 6184865Sobrien /* The base name of this opcode. The names of its completers are 6284865Sobrien appended to it to generate the full instruction name. */ 6384865Sobrien struct string_entry *name; 6484865Sobrien /* The base opcode entry. Which one to use is a fairly arbitrary choice; 6584865Sobrien it uses the first one passed to add_opcode_entry. */ 6684865Sobrien struct ia64_opcode *opcode; 6784865Sobrien /* The list of completers that can be applied to this opcode. */ 6884865Sobrien struct completer_entry *completers; 6984865Sobrien /* Next entry in the chain. */ 7084865Sobrien struct main_entry *next; 7184865Sobrien /* Index in the main table. */ 7284865Sobrien int main_index; 7384865Sobrien} *maintable, **ordered_table; 7484865Sobrienint otlen = 0; 7584865Sobrienint ottotlen = 0; 7684865Sobrienint opcode_count = 0; 7784865Sobrien 7884865Sobrien/* The set of possible completers for an opcode. */ 7984865Sobrienstruct completer_entry 8084865Sobrien{ 8184865Sobrien /* This entry's index in the ia64_completer_table[] array. */ 8284865Sobrien int num; 8384865Sobrien 8484865Sobrien /* The name of the completer. */ 8584865Sobrien struct string_entry *name; 8684865Sobrien 8784865Sobrien /* This entry's parent. */ 8884865Sobrien struct completer_entry *parent; 8984865Sobrien 9084865Sobrien /* Set if this is a terminal completer (occurs at the end of an 9184865Sobrien opcode). */ 9284865Sobrien int is_terminal; 9384865Sobrien 9484865Sobrien /* An alternative completer. */ 9584865Sobrien struct completer_entry *alternative; 9684865Sobrien 9784865Sobrien /* Additional completers that can be appended to this one. */ 9884865Sobrien struct completer_entry *addl_entries; 9984865Sobrien 10084865Sobrien /* Before compute_completer_bits () is invoked, this contains the actual 10184865Sobrien instruction opcode for this combination of opcode and completers. 10284865Sobrien Afterwards, it contains those bits that are different from its 10384865Sobrien parent opcode. */ 10484865Sobrien ia64_insn bits; 10584865Sobrien 10684865Sobrien /* Bits set to 1 correspond to those bits in this completer's opcode 10784865Sobrien that are different from its parent completer's opcode (or from 10884865Sobrien the base opcode if the entry is the root of the opcode's completer 10984865Sobrien list). This field is filled in by compute_completer_bits (). */ 11084865Sobrien ia64_insn mask; 11184865Sobrien 11284865Sobrien /* Index into the opcode dependency list, or -1 if none. */ 11384865Sobrien int dependencies; 11484865Sobrien 11584865Sobrien /* Remember the order encountered in the opcode tables. */ 11684865Sobrien int order; 11784865Sobrien}; 11884865Sobrien 11984865Sobrien/* One entry in the disassembler name table. */ 12084865Sobrienstruct disent 12184865Sobrien{ 12284865Sobrien /* The index into the ia64_name_dis array for this entry. */ 12384865Sobrien int ournum; 12484865Sobrien 12584865Sobrien /* The index into the main_table[] array. */ 12684865Sobrien int insn; 12784865Sobrien 12884865Sobrien /* The disassmbly priority of this entry. */ 12984865Sobrien int priority; 13084865Sobrien 13184865Sobrien /* The completer_index value for this entry. */ 13284865Sobrien int completer_index; 13384865Sobrien 13484865Sobrien /* How many other entries share this decode. */ 13584865Sobrien int nextcnt; 13684865Sobrien 13784865Sobrien /* The next entry sharing the same decode. */ 13884865Sobrien struct disent *nexte; 13984865Sobrien 14084865Sobrien /* The next entry in the name list. */ 14184865Sobrien struct disent *next_ent; 14284865Sobrien} *disinsntable = NULL; 14384865Sobrien 14484865Sobrien/* A state machine that will eventually be used to generate the 14584865Sobrien disassembler table. */ 14684865Sobrienstruct bittree 14784865Sobrien{ 14884865Sobrien struct disent *disent; 14984865Sobrien struct bittree *bits[3]; /* 0, 1, and X (don't care) */ 15084865Sobrien int bits_to_skip; 15184865Sobrien int skip_flag; 15284865Sobrien} *bittree; 15384865Sobrien 15484865Sobrien/* The string table contains all opcodes and completers sorted in 15584865Sobrien alphabetical order. */ 15684865Sobrien 15784865Sobrien/* One entry in the string table. */ 15884865Sobrienstruct string_entry 15984865Sobrien{ 16084865Sobrien /* The index in the ia64_strings[] array for this entry. */ 16184865Sobrien int num; 16284865Sobrien /* And the string. */ 16384865Sobrien char *s; 16484865Sobrien} **string_table = NULL; 16584865Sobrienint strtablen = 0; 16684865Sobrienint strtabtotlen = 0; 16784865Sobrien 16884865Sobrien 16984865Sobrien/* resource dependency entries */ 17084865Sobrienstruct rdep 17184865Sobrien{ 17284865Sobrien char *name; /* resource name */ 17384865Sobrien unsigned 17484865Sobrien mode:2, /* RAW, WAW, or WAR */ 17584865Sobrien semantics:3; /* dependency semantics */ 17684865Sobrien char *extra; /* additional semantics info */ 17784865Sobrien int nchks; 17884865Sobrien int total_chks; /* total #of terminal insns */ 17984865Sobrien int *chks; /* insn classes which read (RAW), write 18084865Sobrien (WAW), or write (WAR) this rsrc */ 18184865Sobrien int *chknotes; /* dependency notes for each class */ 18284865Sobrien int nregs; 18384865Sobrien int total_regs; /* total #of terminal insns */ 18484865Sobrien int *regs; /* insn class which write (RAW), write2 18584865Sobrien (WAW), or read (WAR) this rsrc */ 18684865Sobrien int *regnotes; /* dependency notes for each class */ 18784865Sobrien 18884865Sobrien int waw_special; /* special WAW dependency note */ 18984865Sobrien} **rdeps = NULL; 19084865Sobrien 19184865Sobrienstatic int rdepslen = 0; 19284865Sobrienstatic int rdepstotlen = 0; 19384865Sobrien 19484865Sobrien/* array of all instruction classes */ 19584865Sobrienstruct iclass 19684865Sobrien{ 19784865Sobrien char *name; /* instruction class name */ 19884865Sobrien int is_class; /* is a class, not a terminal */ 19984865Sobrien int nsubs; 20084865Sobrien int *subs; /* other classes within this class */ 20184865Sobrien int nxsubs; 20284865Sobrien int xsubs[4]; /* exclusions */ 20384865Sobrien char *comment; /* optional comment */ 20484865Sobrien int note; /* optional note */ 20584865Sobrien int terminal_resolved; /* did we match this with anything? */ 20684865Sobrien int orphan; /* detect class orphans */ 20784865Sobrien} **ics = NULL; 20884865Sobrien 20984865Sobrienstatic int iclen = 0; 21084865Sobrienstatic int ictotlen = 0; 21184865Sobrien 21284865Sobrien/* an opcode dependency (chk/reg pair of dependency lists) */ 21384865Sobrienstruct opdep 21484865Sobrien{ 21584865Sobrien int chk; /* index into dlists */ 21684865Sobrien int reg; /* index into dlists */ 21784865Sobrien} **opdeps; 21884865Sobrien 21984865Sobrienstatic int opdeplen = 0; 22084865Sobrienstatic int opdeptotlen = 0; 22184865Sobrien 22284865Sobrien/* a generic list of dependencies w/notes encoded. these may be shared. */ 22384865Sobrienstruct deplist 22484865Sobrien{ 22584865Sobrien int len; 22684865Sobrien unsigned short *deps; 22784865Sobrien} **dlists; 22884865Sobrien 22984865Sobrienstatic int dlistlen = 0; 23084865Sobrienstatic int dlisttotlen = 0; 23184865Sobrien 23284865Sobrien/* add NAME to the resource table, where TYPE is RAW or WAW */ 23384865Sobrienstatic struct rdep * 23484865Sobrieninsert_resource (const char *name, enum ia64_dependency_mode type) 23584865Sobrien{ 23684865Sobrien if (rdepslen == rdepstotlen) 23784865Sobrien { 23884865Sobrien rdepstotlen += 20; 23984865Sobrien rdeps = (struct rdep **) 24084865Sobrien xrealloc (rdeps, sizeof(struct rdep **) * rdepstotlen); 24184865Sobrien } 24284865Sobrien rdeps[rdepslen] = tmalloc(struct rdep); 24384865Sobrien memset((void *)rdeps[rdepslen], 0, sizeof(struct rdep)); 24484865Sobrien rdeps[rdepslen]->name = xstrdup (name); 24584865Sobrien rdeps[rdepslen]->mode = type; 24684865Sobrien rdeps[rdepslen]->waw_special = 0; 24784865Sobrien 24884865Sobrien return rdeps[rdepslen++]; 24984865Sobrien} 25084865Sobrien 25184865Sobrien/* are the lists of dependency indexes equivalent? */ 25284865Sobrienstatic int 25384865Sobriendeplist_equals (struct deplist *d1, struct deplist *d2) 25484865Sobrien{ 25584865Sobrien int i; 25684865Sobrien 25784865Sobrien if (d1->len != d2->len) 25884865Sobrien return 0; 25984865Sobrien 26084865Sobrien for (i=0;i < d1->len;i++) 26184865Sobrien { 26284865Sobrien if (d1->deps[i] != d2->deps[i]) 26384865Sobrien return 0; 26484865Sobrien } 26584865Sobrien 26684865Sobrien return 1; 26784865Sobrien} 26884865Sobrien 26984865Sobrien/* add the list of dependencies to the list of dependency lists */ 27084865Sobrienstatic short 27184865Sobrieninsert_deplist(int count, unsigned short *deps) 27284865Sobrien{ 27384865Sobrien /* sort the list, then see if an equivalent list exists already. 27484865Sobrien this results in a much smaller set of dependency lists 27584865Sobrien */ 27684865Sobrien struct deplist *list; 27784865Sobrien char set[0x10000]; 27884865Sobrien int i; 27984865Sobrien 28084865Sobrien memset ((void *)set, 0, sizeof(set)); 28184865Sobrien for (i=0;i < count;i++) 28284865Sobrien set[deps[i]] = 1; 28384865Sobrien count = 0; 28484865Sobrien for (i=0;i < (int)sizeof(set);i++) 28584865Sobrien if (set[i]) 28684865Sobrien ++count; 28784865Sobrien 28884865Sobrien list = tmalloc(struct deplist); 28984865Sobrien list->len = count; 29084865Sobrien list->deps = (unsigned short *)malloc (sizeof(unsigned short) * count); 29184865Sobrien for (i=0, count=0;i < (int)sizeof(set);i++) 29284865Sobrien { 29384865Sobrien if (set[i]) 29484865Sobrien { 29584865Sobrien list->deps[count++] = i; 29684865Sobrien } 29784865Sobrien } 29884865Sobrien 29984865Sobrien /* does this list exist already? */ 30084865Sobrien for (i=0;i < dlistlen;i++) 30184865Sobrien { 30284865Sobrien if (deplist_equals (list, dlists[i])) 30384865Sobrien { 30484865Sobrien free (list->deps); 30584865Sobrien free (list); 30684865Sobrien return i; 30784865Sobrien } 30884865Sobrien } 30984865Sobrien 31084865Sobrien if (dlistlen == dlisttotlen) 31184865Sobrien { 31284865Sobrien dlisttotlen += 20; 31384865Sobrien dlists = (struct deplist **) 31484865Sobrien xrealloc (dlists, sizeof(struct deplist **) * dlisttotlen); 31584865Sobrien } 31684865Sobrien dlists[dlistlen] = list; 31784865Sobrien 31884865Sobrien return dlistlen++; 31984865Sobrien} 32084865Sobrien 32184865Sobrien/* add the given pair of dependency lists to the opcode dependency list */ 32284865Sobrienstatic short 32384865Sobrieninsert_dependencies (int nchks, unsigned short *chks, 32484865Sobrien int nregs, unsigned short *regs) 32584865Sobrien{ 32684865Sobrien struct opdep *pair; 32784865Sobrien int i; 32884865Sobrien int regind = -1; 32984865Sobrien int chkind = -1; 33084865Sobrien 33184865Sobrien if (nregs > 0) 33284865Sobrien regind = insert_deplist (nregs, regs); 33384865Sobrien if (nchks > 0) 33484865Sobrien chkind = insert_deplist (nchks, chks); 33584865Sobrien 33684865Sobrien for (i=0;i < opdeplen;i++) 33784865Sobrien { 33884865Sobrien if (opdeps[i]->chk == chkind 33984865Sobrien && opdeps[i]->reg == regind) 34084865Sobrien return i; 34184865Sobrien } 34284865Sobrien pair = tmalloc(struct opdep); 34384865Sobrien pair->chk = chkind; 34484865Sobrien pair->reg = regind; 34584865Sobrien 34684865Sobrien if (opdeplen == opdeptotlen) 34784865Sobrien { 34884865Sobrien opdeptotlen += 20; 34984865Sobrien opdeps = (struct opdep **) 35084865Sobrien xrealloc (opdeps, sizeof(struct opdep **) * opdeptotlen); 35184865Sobrien } 35284865Sobrien opdeps[opdeplen] = pair; 35384865Sobrien 35484865Sobrien return opdeplen++; 35584865Sobrien} 35684865Sobrien 35784865Sobrienstatic void 35884865Sobrienmark_used (struct iclass *ic, int clear_terminals) 35984865Sobrien{ 36084865Sobrien int i; 36184865Sobrien 36284865Sobrien ic->orphan = 0; 36384865Sobrien if (clear_terminals) 36484865Sobrien ic->terminal_resolved = 1; 36584865Sobrien 36684865Sobrien for (i=0;i < ic->nsubs;i++) 36784865Sobrien { 36884865Sobrien mark_used (ics[ic->subs[i]], clear_terminals); 36984865Sobrien } 37084865Sobrien for (i=0;i < ic->nxsubs;i++) 37184865Sobrien { 37284865Sobrien mark_used (ics[ic->xsubs[i]], clear_terminals); 37384865Sobrien } 37484865Sobrien} 37584865Sobrien 37684865Sobrien/* look up an instruction class; if CREATE make a new one if none found; 37784865Sobrien returns the index into the insn class array */ 37884865Sobrienstatic int 37984865Sobrienfetch_insn_class(const char *full_name, int create) 38084865Sobrien{ 38184865Sobrien char *name; 38284865Sobrien char *notestr; 38384865Sobrien char *xsect; 38484865Sobrien char *comment; 38584865Sobrien int i, note = 0; 38684865Sobrien int ind; 38784865Sobrien int is_class = 0; 38884865Sobrien 38984865Sobrien if (strncmp (full_name, "IC:", 3) == 0) 39084865Sobrien { 39184865Sobrien name = xstrdup (full_name + 3); 39284865Sobrien is_class = 1; 39384865Sobrien } 39484865Sobrien else 39584865Sobrien name = xstrdup (full_name); 39684865Sobrien 39784865Sobrien if ((xsect = strchr(name, '\\')) != NULL) 39884865Sobrien is_class = 1; 39984865Sobrien if ((comment = strchr(name, '[')) != NULL) 40084865Sobrien is_class = 1; 40184865Sobrien if ((notestr = strchr(name, '+')) != NULL) 40284865Sobrien is_class = 1; 40384865Sobrien 40484865Sobrien /* If it is a composite class, then ignore comments and notes that come after 40584865Sobrien the '\\', since they don't apply to the part we are decoding now. */ 40684865Sobrien if (xsect) 40784865Sobrien { 40884865Sobrien if (comment > xsect) 40984865Sobrien comment = 0; 41084865Sobrien if (notestr > xsect) 41184865Sobrien notestr = 0; 41284865Sobrien } 41384865Sobrien 41484865Sobrien if (notestr) 41584865Sobrien { 41684865Sobrien char *nextnotestr; 41784865Sobrien note = atoi (notestr + 1); 41884865Sobrien if ((nextnotestr = strchr (notestr + 1, '+')) != NULL) 41984865Sobrien { 42084865Sobrien if (strcmp (notestr, "+1+13") == 0) 42184865Sobrien note = 13; 42284865Sobrien else if (!xsect || nextnotestr < xsect) 42384865Sobrien fprintf (stderr, "Warning: multiple note %s not handled\n", 42484865Sobrien notestr); 42584865Sobrien } 42684865Sobrien } 42784865Sobrien 42884865Sobrien /* If it's a composite class, leave the notes and comments in place so that 42984865Sobrien we have a unique name for the composite class. Otherwise, we remove 43084865Sobrien them. */ 43184865Sobrien if (!xsect) 43284865Sobrien { 43384865Sobrien if (notestr) 43484865Sobrien *notestr = 0; 43584865Sobrien if (comment) 43684865Sobrien *comment = 0; 43784865Sobrien } 43884865Sobrien 43984865Sobrien for (i=0;i < iclen;i++) 44084865Sobrien if (strcmp(name, ics[i]->name) == 0 44184865Sobrien && ((comment == NULL && ics[i]->comment == NULL) 44284865Sobrien || (comment != NULL && ics[i]->comment != NULL 44384865Sobrien && strncmp (ics[i]->comment, comment, 44484865Sobrien strlen (ics[i]->comment)) == 0)) 44584865Sobrien && note == ics[i]->note) 44684865Sobrien return i; 44784865Sobrien 44884865Sobrien if (!create) 44984865Sobrien return -1; 45084865Sobrien 45184865Sobrien /* doesn't exist, so make a new one */ 45284865Sobrien if (iclen == ictotlen) 45384865Sobrien { 45484865Sobrien ictotlen += 20; 45584865Sobrien ics = (struct iclass **) 45684865Sobrien xrealloc(ics, (ictotlen)*sizeof(struct iclass *)); 45784865Sobrien } 45884865Sobrien ind = iclen++; 45984865Sobrien ics[ind] = tmalloc(struct iclass); 46084865Sobrien memset((void *)ics[ind], 0, sizeof(struct iclass)); 46184865Sobrien ics[ind]->name = xstrdup(name); 46284865Sobrien ics[ind]->is_class = is_class; 46384865Sobrien ics[ind]->orphan = 1; 46484865Sobrien 46584865Sobrien if (comment) 46684865Sobrien { 46784865Sobrien ics[ind]->comment = xstrdup (comment + 1); 46884865Sobrien ics[ind]->comment[strlen(ics[ind]->comment)-1] = 0; 46984865Sobrien } 47084865Sobrien if (notestr) 47184865Sobrien ics[ind]->note = note; 47284865Sobrien 47384865Sobrien /* if it's a composite class, there's a comment or note, look for an 47484865Sobrien existing class or terminal with the same name. */ 47584865Sobrien if ((xsect || comment || notestr) && is_class) 47684865Sobrien { 47784865Sobrien /* First, populate with the class we're based on. */ 47884865Sobrien char *subname = name; 47984865Sobrien if (xsect) 48084865Sobrien *xsect = 0; 48184865Sobrien else if (comment) 48284865Sobrien *comment = 0; 48384865Sobrien else if (notestr) 48484865Sobrien *notestr = 0; 48584865Sobrien ics[ind]->nsubs = 1; 48684865Sobrien ics[ind]->subs = tmalloc(int); 48784865Sobrien ics[ind]->subs[0] = fetch_insn_class (subname, 1);; 48884865Sobrien } 48984865Sobrien 49084865Sobrien while (xsect) 49184865Sobrien { 49284865Sobrien char *subname = xsect + 1; 49384865Sobrien xsect = strchr (subname, '\\'); 49484865Sobrien if (xsect) 49584865Sobrien *xsect = 0; 49684865Sobrien ics[ind]->xsubs[ics[ind]->nxsubs] = fetch_insn_class (subname,1); 49784865Sobrien ics[ind]->nxsubs++; 49884865Sobrien } 49984865Sobrien free (name); 50084865Sobrien 50184865Sobrien return ind; 50284865Sobrien} 50384865Sobrien 50484865Sobrien/* for sorting a class's sub-class list only; make sure classes appear before 50584865Sobrien terminals */ 50684865Sobrienstatic int 50784865Sobriensub_compare (const void *e1, const void *e2) 50884865Sobrien{ 50984865Sobrien struct iclass *ic1 = ics[*(int *)e1]; 51084865Sobrien struct iclass *ic2 = ics[*(int *)e2]; 51184865Sobrien 51284865Sobrien if (ic1->is_class) 51384865Sobrien { 51484865Sobrien if (!ic2->is_class) 51584865Sobrien return -1; 51684865Sobrien } 51784865Sobrien else if (ic2->is_class) 51884865Sobrien return 1; 51984865Sobrien 52084865Sobrien return strcmp (ic1->name, ic2->name); 52184865Sobrien} 52284865Sobrien 52384865Sobrienstatic void 52484865Sobrienload_insn_classes() 52584865Sobrien{ 52684865Sobrien FILE *fp = fopen("ia64-ic.tbl", "r"); 52784865Sobrien char buf[2048]; 52884865Sobrien 52984865Sobrien if (fp == NULL){ 53084865Sobrien fprintf (stderr, "Can't find ia64-ic.tbl for reading\n"); 53184865Sobrien exit(1); 53284865Sobrien } 53384865Sobrien 53484865Sobrien /* discard first line */ 53584865Sobrien fgets (buf, sizeof(buf), fp); 53684865Sobrien 53784865Sobrien while (!feof(fp)) 53884865Sobrien { 53984865Sobrien int iclass; 54084865Sobrien char *name; 54184865Sobrien char *tmp; 54284865Sobrien 54384865Sobrien if (fgets (buf, sizeof(buf), fp) == NULL) 54484865Sobrien break; 54584865Sobrien 54684865Sobrien while (isspace(buf[strlen(buf)-1])) 54784865Sobrien buf[strlen(buf)-1] = '\0'; 54884865Sobrien 54984865Sobrien name = tmp = buf; 55084865Sobrien while (*tmp != ';') 55184865Sobrien { 55284865Sobrien ++tmp; 55384865Sobrien if (tmp == buf + sizeof(buf)) 55484865Sobrien abort (); 55584865Sobrien } 55684865Sobrien *tmp++ = '\0'; 55784865Sobrien 55884865Sobrien iclass = fetch_insn_class(name, 1); 55984865Sobrien ics[iclass]->is_class = 1; 56084865Sobrien 56184865Sobrien if (strcmp (name, "none") == 0) 56284865Sobrien { 56384865Sobrien ics[iclass]->is_class = 0; 56484865Sobrien ics[iclass]->terminal_resolved = 1; 56584865Sobrien continue; 56684865Sobrien } 56784865Sobrien 56884865Sobrien /* for this class, record all sub-classes */ 56984865Sobrien while (*tmp) 57084865Sobrien { 57184865Sobrien char *subname; 57284865Sobrien int sub; 57384865Sobrien 57484865Sobrien while (*tmp && isspace(*tmp)) 57584865Sobrien { 57684865Sobrien ++tmp; 57784865Sobrien if (tmp == buf + sizeof(buf)) 57884865Sobrien abort(); 57984865Sobrien } 58084865Sobrien subname = tmp; 58184865Sobrien while (*tmp && *tmp != ',') 58284865Sobrien { 58384865Sobrien ++tmp; 58484865Sobrien if (tmp == buf + sizeof(buf)) 58584865Sobrien abort(); 58684865Sobrien } 58784865Sobrien if (*tmp == ',') 58884865Sobrien *tmp++ = '\0'; 58984865Sobrien 59084865Sobrien ics[iclass]->subs = (int *) 59184865Sobrien xrealloc((void *)ics[iclass]->subs, 59284865Sobrien (ics[iclass]->nsubs+1)*sizeof(int)); 59384865Sobrien 59484865Sobrien sub = fetch_insn_class(subname, 1); 59584865Sobrien ics[iclass]->subs = (int *) 59684865Sobrien xrealloc(ics[iclass]->subs, (ics[iclass]->nsubs+1)*sizeof(int)); 59784865Sobrien ics[iclass]->subs[ics[iclass]->nsubs++] = sub; 59884865Sobrien } 59984865Sobrien /* make sure classes come before terminals */ 60084865Sobrien qsort ((void *)ics[iclass]->subs, 60184865Sobrien ics[iclass]->nsubs, sizeof(int), sub_compare); 60284865Sobrien } 60384865Sobrien fclose(fp); 60484865Sobrien 60584865Sobrien if (debug) 60684865Sobrien { 60784865Sobrien printf ("%d classes\n", iclen); 60884865Sobrien } 60984865Sobrien} 61084865Sobrien 61184865Sobrien/* extract the insn classes from the given line */ 61284865Sobrienstatic void 61384865Sobrienparse_resource_users(ref, usersp, nusersp, notesp) 61484865Sobrien char *ref; 61584865Sobrien int **usersp; 61684865Sobrien int *nusersp; 61784865Sobrien int **notesp; 61884865Sobrien{ 61984865Sobrien int c; 62084865Sobrien char *line = xstrdup (ref); 62184865Sobrien char *tmp = line; 62284865Sobrien int *users = *usersp; 62384865Sobrien int count = *nusersp; 62484865Sobrien int *notes = *notesp; 62584865Sobrien 62684865Sobrien c = *tmp; 62784865Sobrien while (c != 0) 62884865Sobrien { 62984865Sobrien char *notestr; 63084865Sobrien int note; 63184865Sobrien char *xsect; 63284865Sobrien int iclass; 63384865Sobrien int create = 0; 63484865Sobrien char *name; 63584865Sobrien 63684865Sobrien while (isspace(*tmp)) 63784865Sobrien ++tmp; 63884865Sobrien name = tmp; 63984865Sobrien while (*tmp && *tmp != ',') 64084865Sobrien ++tmp; 64184865Sobrien c = *tmp; 64284865Sobrien *tmp++ = '\0'; 64384865Sobrien 64484865Sobrien xsect = strchr(name, '\\'); 64584865Sobrien if ((notestr = strstr(name, "+")) != NULL) 64684865Sobrien { 64784865Sobrien char *nextnotestr; 64884865Sobrien note = atoi (notestr + 1); 64984865Sobrien if ((nextnotestr = strchr (notestr + 1, '+')) != NULL) 65084865Sobrien { 65184865Sobrien /* note 13 always implies note 1 */ 65284865Sobrien if (strcmp (notestr, "+1+13") == 0) 65384865Sobrien note = 13; 65484865Sobrien else if (!xsect || nextnotestr < xsect) 65584865Sobrien fprintf (stderr, "Warning: multiple note %s not handled\n", 65684865Sobrien notestr); 65784865Sobrien } 65884865Sobrien if (!xsect) 65984865Sobrien *notestr = '\0'; 66084865Sobrien } 66184865Sobrien else 66284865Sobrien note = 0; 66384865Sobrien 66484865Sobrien /* All classes are created when the insn class table is parsed; 66584865Sobrien Individual instructions might not appear until the dependency tables 66684865Sobrien are read. Only create new classes if it's *not* an insn class, 66784865Sobrien or if it's a composite class (which wouldn't necessarily be in the IC 66884865Sobrien table). 66984865Sobrien */ 67084865Sobrien if (strncmp(name, "IC:", 3) != 0 || xsect != NULL) 67184865Sobrien create = 1; 67284865Sobrien 67384865Sobrien iclass = fetch_insn_class(name, create); 67484865Sobrien if (iclass != -1) 67584865Sobrien { 67684865Sobrien users = (int *) 67784865Sobrien xrealloc ((void *)users,(count+1)*sizeof(int)); 67884865Sobrien notes = (int *) 67984865Sobrien xrealloc ((void *)notes,(count+1)*sizeof(int)); 68084865Sobrien notes[count] = note; 68184865Sobrien users[count++] = iclass; 68284865Sobrien mark_used (ics[iclass], 0); 68384865Sobrien } 68484865Sobrien else 68584865Sobrien { 68684865Sobrien if (debug) 68784865Sobrien printf("Class %s not found\n", name); 68884865Sobrien } 68984865Sobrien } 69084865Sobrien /* update the return values */ 69184865Sobrien *usersp = users; 69284865Sobrien *nusersp = count; 69384865Sobrien *notesp = notes; 69484865Sobrien 69584865Sobrien free (line); 69684865Sobrien} 69784865Sobrien 69884865Sobrienstatic int 69984865Sobrienparse_semantics (char *sem) 70084865Sobrien{ 70184865Sobrien if (strcmp (sem, "none") == 0) 70284865Sobrien return IA64_DVS_NONE; 70384865Sobrien else if (strcmp (sem, "implied") == 0) 70484865Sobrien return IA64_DVS_IMPLIED; 70584865Sobrien else if (strcmp (sem, "impliedF") == 0) 70684865Sobrien return IA64_DVS_IMPLIEDF; 70784865Sobrien else if (strcmp (sem, "data") == 0) 70884865Sobrien return IA64_DVS_DATA; 70984865Sobrien else if (strcmp (sem, "instr") == 0) 71084865Sobrien return IA64_DVS_INSTR; 71184865Sobrien else if (strcmp (sem, "specific") == 0) 71284865Sobrien return IA64_DVS_SPECIFIC; 71384865Sobrien else if (strcmp (sem, "stop") == 0) 71484865Sobrien return IA64_DVS_STOP; 71584865Sobrien else 71684865Sobrien return IA64_DVS_OTHER; 71784865Sobrien} 71884865Sobrien 71984865Sobrienstatic void 72084865Sobrienadd_dep (const char *name, const char *chk, const char *reg, 72184865Sobrien int semantics, int mode, char *extra, int flag) 72284865Sobrien{ 72384865Sobrien struct rdep *rs; 72484865Sobrien 72584865Sobrien rs = insert_resource (name, mode); 72684865Sobrien parse_resource_users (chk, &rs->chks, &rs->nchks, 72784865Sobrien &rs->chknotes); 72884865Sobrien parse_resource_users (reg, &rs->regs, &rs->nregs, 72984865Sobrien &rs->regnotes); 73084865Sobrien rs->semantics = semantics; 73184865Sobrien rs->extra = extra; 73284865Sobrien rs->waw_special = flag; 73384865Sobrien} 73484865Sobrien 73584865Sobrienstatic void 73684865Sobrienload_depfile (const char *filename, enum ia64_dependency_mode mode) 73784865Sobrien{ 73884865Sobrien FILE *fp = fopen(filename, "r"); 73984865Sobrien char buf[1024]; 74084865Sobrien 74184865Sobrien if (fp == NULL){ 74284865Sobrien fprintf (stderr, "Can't find %s for reading\n", filename); 74384865Sobrien exit(1); 74484865Sobrien } 74584865Sobrien 74684865Sobrien fgets(buf, sizeof(buf), fp); 74784865Sobrien while (!feof(fp)) 74884865Sobrien { 74984865Sobrien char *name, *tmp; 75084865Sobrien int semantics; 75184865Sobrien char *extra; 75284865Sobrien char *regp, *chkp; 75384865Sobrien 75484865Sobrien if (fgets (buf, sizeof(buf), fp) == NULL) 75584865Sobrien break; 75684865Sobrien 75784865Sobrien while (isspace(buf[strlen(buf)-1])) 75884865Sobrien buf[strlen(buf)-1] = '\0'; 75984865Sobrien 76084865Sobrien name = tmp = buf; 76184865Sobrien while (*tmp != ';') 76284865Sobrien ++tmp; 76384865Sobrien *tmp++ = '\0'; 76484865Sobrien 76584865Sobrien while (isspace (*tmp)) 76684865Sobrien ++tmp; 76784865Sobrien regp = tmp; 76884865Sobrien tmp = strchr (tmp, ';'); 76984865Sobrien if (!tmp) 77084865Sobrien abort (); 77184865Sobrien *tmp++ = 0; 77284865Sobrien while (isspace (*tmp)) 77384865Sobrien ++tmp; 77484865Sobrien chkp = tmp; 77584865Sobrien tmp = strchr (tmp, ';'); 77684865Sobrien if (!tmp) 77784865Sobrien abort (); 77884865Sobrien *tmp++ = 0; 77984865Sobrien while (isspace (*tmp)) 78084865Sobrien ++tmp; 78184865Sobrien semantics = parse_semantics (tmp); 78284865Sobrien extra = semantics == IA64_DVS_OTHER ? xstrdup (tmp) : NULL; 78384865Sobrien 78484865Sobrien /* For WAW entries, if the chks and regs differ, we need to enter the 78584865Sobrien entries in both positions so that the tables will be parsed properly, 78684865Sobrien without a lot of extra work */ 78784865Sobrien if (mode == IA64_DV_WAW && strcmp (regp, chkp) != 0) 78884865Sobrien { 78984865Sobrien add_dep (name, chkp, regp, semantics, mode, extra, 0); 79084865Sobrien add_dep (name, regp, chkp, semantics, mode, extra, 1); 79184865Sobrien } 79284865Sobrien else 79384865Sobrien { 79484865Sobrien add_dep (name, chkp, regp, semantics, mode, extra, 0); 79584865Sobrien } 79684865Sobrien } 79784865Sobrien fclose(fp); 79884865Sobrien} 79984865Sobrien 80084865Sobrienstatic void 80184865Sobrienload_dependencies() 80284865Sobrien{ 80384865Sobrien load_depfile ("ia64-raw.tbl", IA64_DV_RAW); 80484865Sobrien load_depfile ("ia64-waw.tbl", IA64_DV_WAW); 80584865Sobrien load_depfile ("ia64-war.tbl", IA64_DV_WAR); 80684865Sobrien 80784865Sobrien if (debug) 80884865Sobrien printf ("%d RAW/WAW/WAR dependencies\n", rdepslen); 80984865Sobrien} 81084865Sobrien 81184865Sobrien/* is the given operand an indirect register file operand? */ 81284865Sobrienstatic int 81384865Sobrienirf_operand (int op, const char *field) 81484865Sobrien{ 81584865Sobrien if (!field) 81684865Sobrien { 81784865Sobrien return op == IA64_OPND_RR_R3 || op == IA64_OPND_DBR_R3 81884865Sobrien || op == IA64_OPND_IBR_R3 || op == IA64_OPND_PKR_R3 81984865Sobrien || op == IA64_OPND_PMC_R3 || op == IA64_OPND_PMD_R3 82084865Sobrien || op == IA64_OPND_MSR_R3 || op == IA64_OPND_CPUID_R3; 82184865Sobrien } 82284865Sobrien else 82384865Sobrien { 82484865Sobrien return ((op == IA64_OPND_RR_R3 && strstr (field, "rr")) 82584865Sobrien || (op == IA64_OPND_DBR_R3 && strstr (field, "dbr")) 82684865Sobrien || (op == IA64_OPND_IBR_R3 && strstr (field, "ibr")) 82784865Sobrien || (op == IA64_OPND_PKR_R3 && strstr (field, "pkr")) 82884865Sobrien || (op == IA64_OPND_PMC_R3 && strstr (field, "pmc")) 82984865Sobrien || (op == IA64_OPND_PMD_R3 && strstr (field, "pmd")) 83084865Sobrien || (op == IA64_OPND_MSR_R3 && strstr (field, "msr")) 83184865Sobrien || (op == IA64_OPND_CPUID_R3 && strstr (field, "cpuid"))); 83284865Sobrien } 83384865Sobrien} 83484865Sobrien 83584865Sobrien/* handle mov_ar, mov_br, mov_cr, mov_indirect, mov_ip, mov_pr, mov_psr, and 83684865Sobrien mov_um insn classes */ 83784865Sobrienstatic int 83884865Sobrienin_iclass_mov_x (struct ia64_opcode *idesc, struct iclass *ic, 83984865Sobrien const char *format, const char *field) 84084865Sobrien{ 84184865Sobrien int plain_mov = strcmp (idesc->name, "mov") == 0; 84284865Sobrien 84384865Sobrien if (!format) 84484865Sobrien return 0; 84584865Sobrien 84684865Sobrien switch (ic->name[4]) 84784865Sobrien { 84884865Sobrien default: 84984865Sobrien abort (); 85084865Sobrien case 'a': 85184865Sobrien { 85284865Sobrien int i = strcmp (idesc->name, "mov.i") == 0; 85384865Sobrien int m = strcmp (idesc->name, "mov.m") == 0; 85484865Sobrien int i2627 = i && idesc->operands[0] == IA64_OPND_AR3; 85584865Sobrien int i28 = i && idesc->operands[1] == IA64_OPND_AR3; 85684865Sobrien int m2930 = m && idesc->operands[0] == IA64_OPND_AR3; 85784865Sobrien int m31 = m && idesc->operands[1] == IA64_OPND_AR3; 85884865Sobrien int pseudo0 = plain_mov && idesc->operands[1] == IA64_OPND_AR3; 85984865Sobrien int pseudo1 = plain_mov && idesc->operands[0] == IA64_OPND_AR3; 86084865Sobrien 86184865Sobrien /* IC:mov ar */ 86284865Sobrien if (i2627) 86384865Sobrien return strstr (format, "I26") || strstr (format, "I27"); 86484865Sobrien if (i28) 86584865Sobrien return strstr (format, "I28") != NULL; 86684865Sobrien if (m2930) 86784865Sobrien return strstr (format, "M29") || strstr (format, "M30"); 86884865Sobrien if (m31) 86984865Sobrien return strstr (format, "M31") != NULL; 87084865Sobrien if (pseudo0 || pseudo1) 87184865Sobrien return 1; 87284865Sobrien } 87384865Sobrien break; 87484865Sobrien case 'b': 87584865Sobrien { 87684865Sobrien int i21 = idesc->operands[0] == IA64_OPND_B1; 87784865Sobrien int i22 = plain_mov && idesc->operands[1] == IA64_OPND_B2; 87884865Sobrien if (i22) 87984865Sobrien return strstr (format, "I22") != NULL; 88084865Sobrien if (i21) 88184865Sobrien return strstr (format, "I21") != NULL; 88284865Sobrien } 88384865Sobrien break; 88484865Sobrien case 'c': 88584865Sobrien { 88684865Sobrien int m32 = plain_mov && idesc->operands[0] == IA64_OPND_CR3; 88784865Sobrien int m33 = plain_mov && idesc->operands[1] == IA64_OPND_CR3; 88884865Sobrien if (m32) 88984865Sobrien return strstr (format, "M32") != NULL; 89084865Sobrien if (m33) 89184865Sobrien return strstr (format, "M33") != NULL; 89284865Sobrien } 89384865Sobrien break; 89484865Sobrien case 'i': 89584865Sobrien if (ic->name[5] == 'n') 89684865Sobrien { 89784865Sobrien int m42 = plain_mov && irf_operand (idesc->operands[0], field); 89884865Sobrien int m43 = plain_mov && irf_operand (idesc->operands[1], field); 89984865Sobrien if (m42) 90084865Sobrien return strstr (format, "M42") != NULL; 90184865Sobrien if (m43) 90284865Sobrien return strstr (format, "M43") != NULL; 90384865Sobrien } 90484865Sobrien else if (ic->name[5] == 'p') 90584865Sobrien { 90684865Sobrien return idesc->operands[1] == IA64_OPND_IP; 90784865Sobrien } 90884865Sobrien else 90984865Sobrien abort (); 91084865Sobrien break; 91184865Sobrien case 'p': 91284865Sobrien if (ic->name[5] == 'r') 91384865Sobrien { 91484865Sobrien int i25 = plain_mov && idesc->operands[1] == IA64_OPND_PR; 91584865Sobrien int i23 = plain_mov && idesc->operands[0] == IA64_OPND_PR; 91684865Sobrien int i24 = plain_mov && idesc->operands[0] == IA64_OPND_PR_ROT; 91784865Sobrien if (i23) 91884865Sobrien return strstr (format, "I23") != NULL; 91984865Sobrien if (i24) 92084865Sobrien return strstr (format, "I24") != NULL; 92184865Sobrien if (i25) 92284865Sobrien return strstr (format, "I25") != NULL; 92384865Sobrien } 92484865Sobrien else if (ic->name[5] == 's') 92584865Sobrien { 92684865Sobrien int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_L; 92784865Sobrien int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR; 92884865Sobrien if (m35) 92984865Sobrien return strstr (format, "M35") != NULL; 93084865Sobrien if (m36) 93184865Sobrien return strstr (format, "M36") != NULL; 93284865Sobrien } 93384865Sobrien else 93484865Sobrien abort (); 93584865Sobrien break; 93684865Sobrien case 'u': 93784865Sobrien { 93884865Sobrien int m35 = plain_mov && idesc->operands[0] == IA64_OPND_PSR_UM; 93984865Sobrien int m36 = plain_mov && idesc->operands[1] == IA64_OPND_PSR_UM; 94084865Sobrien if (m35) 94184865Sobrien return strstr (format, "M35") != NULL; 94284865Sobrien if (m36) 94384865Sobrien return strstr (format, "M36") != NULL; 94484865Sobrien } 94584865Sobrien break; 94684865Sobrien } 94784865Sobrien return 0; 94884865Sobrien} 94984865Sobrien 95084865Sobrien 95184865Sobrien/* is the given opcode in the given insn class? */ 95284865Sobrienstatic int 95384865Sobrienin_iclass(struct ia64_opcode *idesc, struct iclass *ic, 95484865Sobrien const char *format, const char *field, int *notep) 95584865Sobrien{ 95684865Sobrien int i; 95784865Sobrien int resolved = 0; 95884865Sobrien 95984865Sobrien if (ic->comment) 96084865Sobrien { 96184865Sobrien if (!strncmp (ic->comment, "Format", 6)) 96284865Sobrien { 96384865Sobrien /* assume that the first format seen is the most restrictive, and 96484865Sobrien only keep a later one if it looks like it's more restrictive. */ 96584865Sobrien if (format) 96684865Sobrien { 96784865Sobrien if (strlen (ic->comment) < strlen (format)) 96884865Sobrien { 96984865Sobrien fprintf (stderr, "Warning: most recent format '%s'\n" 97084865Sobrien "appears more restrictive than '%s'\n", 97184865Sobrien ic->comment, format); 97284865Sobrien format = ic->comment; 97384865Sobrien } 97484865Sobrien } 97584865Sobrien else 97684865Sobrien format = ic->comment; 97784865Sobrien } 97884865Sobrien else if (!strncmp (ic->comment, "Field", 5)) 97984865Sobrien { 98084865Sobrien if (field) 98184865Sobrien fprintf (stderr, "Overlapping field %s->%s\n", 98284865Sobrien ic->comment, field); 98384865Sobrien field = ic->comment; 98484865Sobrien } 98584865Sobrien } 98684865Sobrien 98784865Sobrien /* an insn class matches anything that is the same followed by completers, 98884865Sobrien except when the absence and presence of completers constitutes different 98984865Sobrien instructions */ 99084865Sobrien if (ic->nsubs == 0 && ic->nxsubs == 0) 99184865Sobrien { 99284865Sobrien int is_mov = strncmp (idesc->name, "mov", 3) == 0; 99384865Sobrien int plain_mov = strcmp (idesc->name, "mov") == 0; 99484865Sobrien int len = strlen(ic->name); 99584865Sobrien 99684865Sobrien resolved = ((strncmp (ic->name, idesc->name, len) == 0) 99784865Sobrien && (idesc->name[len] == '\0' 99884865Sobrien || idesc->name[len] == '.')); 99984865Sobrien 100084865Sobrien /* all break and nop variations must match exactly */ 100184865Sobrien if (resolved && 100284865Sobrien (strcmp (ic->name, "break") == 0 100384865Sobrien || strcmp (ic->name, "nop") == 0)) 100484865Sobrien resolved = strcmp (ic->name, idesc->name) == 0; 100584865Sobrien 100684865Sobrien /* assume restrictions in the FORMAT/FIELD negate resolution, 100784865Sobrien unless specifically allowed by clauses in this block */ 100884865Sobrien if (resolved && field) 100984865Sobrien { 101084865Sobrien /* check Field(sf)==sN against opcode sN */ 101184865Sobrien if (strstr(field, "(sf)==") != NULL) 101284865Sobrien { 101384865Sobrien char *sf; 101484865Sobrien if ((sf = strstr (idesc->name, ".s")) != 0) 101584865Sobrien { 101684865Sobrien resolved = strcmp (sf + 1, strstr (field, "==") + 2) == 0; 101784865Sobrien } 101884865Sobrien } 101984865Sobrien /* check Field(lftype)==XXX */ 102084865Sobrien else if (strstr (field, "(lftype)") != NULL) 102184865Sobrien { 102284865Sobrien if (strstr (idesc->name, "fault") != NULL) 102384865Sobrien resolved = strstr (field, "fault") != NULL; 102484865Sobrien else 102584865Sobrien resolved = strstr (field, "fault") == NULL; 102684865Sobrien } 102784865Sobrien /* handle Field(ctype)==XXX */ 102884865Sobrien else if (strstr (field, "(ctype)") != NULL) 102984865Sobrien { 103084865Sobrien if (strstr (idesc->name, "or.andcm")) 103184865Sobrien resolved = strstr (field, "or.andcm") != NULL; 103284865Sobrien else if (strstr (idesc->name, "and.orcm")) 103384865Sobrien resolved = strstr (field, "and.orcm") != NULL; 103484865Sobrien else if (strstr (idesc->name, "orcm")) 103584865Sobrien resolved = strstr (field, "or orcm") != NULL; 103684865Sobrien else if (strstr (idesc->name, "or")) 103784865Sobrien resolved = strstr (field, "or orcm") != NULL; 103884865Sobrien else if (strstr (idesc->name, "andcm")) 103984865Sobrien resolved = strstr (field, "and andcm") != NULL; 104084865Sobrien else if (strstr (idesc->name, "and")) 104184865Sobrien resolved = strstr (field, "and andcm") != NULL; 104284865Sobrien else if (strstr (idesc->name, "unc")) 104384865Sobrien resolved = strstr (field, "unc") != NULL; 104484865Sobrien else 104584865Sobrien resolved = strcmp (field, "Field(ctype)==") == 0; 104684865Sobrien } 104784865Sobrien } 104884865Sobrien if (resolved && format) 104984865Sobrien { 105084865Sobrien if (strncmp (idesc->name, "dep", 3) == 0 105184865Sobrien && strstr (format, "I13") != NULL) 105284865Sobrien resolved = idesc->operands[1] == IA64_OPND_IMM8; 105384865Sobrien else if (strncmp (idesc->name, "chk", 3) == 0 105484865Sobrien && strstr (format, "M21") != NULL) 105584865Sobrien resolved = idesc->operands[0] == IA64_OPND_F2; 105684865Sobrien else if (strncmp (idesc->name, "lfetch", 6) == 0) 105784865Sobrien resolved = (strstr (format, "M14 M15") != NULL 105884865Sobrien && (idesc->operands[1] == IA64_OPND_R2 105984865Sobrien || idesc->operands[1] == IA64_OPND_IMM9b)); 106084865Sobrien else if (strncmp (idesc->name, "br.call", 7) == 0 106184865Sobrien && strstr (format, "B5") != NULL) 106284865Sobrien resolved = idesc->operands[1] == IA64_OPND_B2; 106384865Sobrien else if (strncmp (idesc->name, "br.call", 7) == 0 106484865Sobrien && strstr (format, "B3") != NULL) 106584865Sobrien resolved = idesc->operands[1] == IA64_OPND_TGT25c; 106684865Sobrien else if (strncmp (idesc->name, "brp", 3) == 0 106784865Sobrien && strstr (format, "B7") != NULL) 106884865Sobrien resolved = idesc->operands[0] == IA64_OPND_B2; 106984865Sobrien else if (strcmp (ic->name, "invala") == 0) 107084865Sobrien resolved = strcmp (idesc->name, ic->name) == 0; 107184865Sobrien else if (strncmp (idesc->name, "st", 2) == 0 107284865Sobrien && strstr (format, "M5") != NULL) 107384865Sobrien resolved = idesc->flags & IA64_OPCODE_POSTINC; 107484865Sobrien else 107584865Sobrien resolved = 0; 107684865Sobrien } 107784865Sobrien 107884865Sobrien /* misc brl variations ('.cond' is optional); 107984865Sobrien plain brl matches brl.cond */ 108084865Sobrien if (!resolved 108184865Sobrien && (strcmp (idesc->name, "brl") == 0 108284865Sobrien || strncmp (idesc->name, "brl.", 4) == 0) 108384865Sobrien && strcmp (ic->name, "brl.cond") == 0) 108484865Sobrien { 108584865Sobrien resolved = 1; 108684865Sobrien } 108784865Sobrien 108884865Sobrien /* misc br variations ('.cond' is optional) */ 108984865Sobrien if (!resolved 109084865Sobrien && (strcmp (idesc->name, "br") == 0 109184865Sobrien || strncmp (idesc->name, "br.", 3) == 0) 109284865Sobrien && strcmp (ic->name, "br.cond") == 0) 109384865Sobrien { 109484865Sobrien if (format) 109584865Sobrien resolved = (strstr (format, "B4") != NULL 109684865Sobrien && idesc->operands[0] == IA64_OPND_B2) 109784865Sobrien || (strstr (format, "B1") != NULL 109884865Sobrien && idesc->operands[0] == IA64_OPND_TGT25c); 109984865Sobrien else 110084865Sobrien resolved = 1; 110184865Sobrien } 110284865Sobrien 110384865Sobrien /* probe variations */ 110484865Sobrien if (!resolved && strncmp (idesc->name, "probe", 5) == 0) 110584865Sobrien { 110684865Sobrien resolved = strcmp (ic->name, "probe") == 0 110784865Sobrien && !((strstr (idesc->name, "fault") != NULL) 110884865Sobrien ^ (format && strstr (format, "M40") != NULL)); 110984865Sobrien } 111084865Sobrien /* mov variations */ 111184865Sobrien if (!resolved && is_mov) 111284865Sobrien { 111384865Sobrien if (plain_mov) 111484865Sobrien { 111584865Sobrien /* mov alias for fmerge */ 111684865Sobrien if (strcmp (ic->name, "fmerge") == 0) 111784865Sobrien { 111884865Sobrien resolved = idesc->operands[0] == IA64_OPND_F1 111984865Sobrien && idesc->operands[1] == IA64_OPND_F3; 112084865Sobrien } 112184865Sobrien /* mov alias for adds (r3 or imm14) */ 112284865Sobrien else if (strcmp (ic->name, "adds") == 0) 112384865Sobrien { 112484865Sobrien resolved = (idesc->operands[0] == IA64_OPND_R1 112584865Sobrien && (idesc->operands[1] == IA64_OPND_R3 112684865Sobrien || (idesc->operands[1] == IA64_OPND_IMM14))); 112784865Sobrien } 112884865Sobrien /* mov alias for addl */ 112984865Sobrien else if (strcmp (ic->name, "addl") == 0) 113084865Sobrien { 113184865Sobrien resolved = idesc->operands[0] == IA64_OPND_R1 113284865Sobrien && idesc->operands[1] == IA64_OPND_IMM22; 113384865Sobrien } 113484865Sobrien } 113584865Sobrien /* some variants of mov and mov.[im] */ 113684865Sobrien if (!resolved && strncmp (ic->name, "mov_", 4) == 0) 113784865Sobrien { 113884865Sobrien resolved = in_iclass_mov_x (idesc, ic, format, field); 113984865Sobrien } 114084865Sobrien } 114184865Sobrien 114284865Sobrien /* keep track of this so we can flag any insn classes which aren't 114384865Sobrien mapped onto at least one real insn */ 114484865Sobrien if (resolved) 114584865Sobrien { 114684865Sobrien ic->terminal_resolved = 1; 114784865Sobrien } 114884865Sobrien } 114984865Sobrien else for (i=0;i < ic->nsubs;i++) 115084865Sobrien { 115184865Sobrien if (in_iclass(idesc, ics[ic->subs[i]], format, field, notep)) 115284865Sobrien { 115384865Sobrien int j; 115484865Sobrien for (j=0;j < ic->nxsubs;j++) 115584865Sobrien { 115684865Sobrien if (in_iclass(idesc, ics[ic->xsubs[j]], NULL, NULL, NULL)) 115784865Sobrien return 0; 115884865Sobrien } 115984865Sobrien if (debug > 1) 116084865Sobrien printf ("%s is in IC %s\n", 116184865Sobrien idesc->name, ic->name); 116284865Sobrien resolved = 1; 116384865Sobrien break; 116484865Sobrien } 116584865Sobrien } 116684865Sobrien 116784865Sobrien /* If it's in this IC, add the IC note (if any) to the insn */ 116884865Sobrien if (resolved) 116984865Sobrien { 117084865Sobrien if (ic->note && notep) 117184865Sobrien { 117284865Sobrien if (*notep && *notep != ic->note) 117384865Sobrien { 117484865Sobrien fprintf (stderr, "Warning: overwriting note %d with note %d" 117584865Sobrien "(IC:%s)\n", 117684865Sobrien *notep, ic->note, ic->name); 117784865Sobrien } 117884865Sobrien *notep = ic->note; 117984865Sobrien } 118084865Sobrien } 118184865Sobrien 118284865Sobrien return resolved; 118384865Sobrien} 118484865Sobrien 118584865Sobrien 118684865Sobrienstatic int 118784865Sobrienlookup_regindex (const char *name, int specifier) 118884865Sobrien{ 118984865Sobrien switch (specifier) 119084865Sobrien { 119184865Sobrien case IA64_RS_ARX: 119284865Sobrien if (strstr (name, "[RSC]")) 119384865Sobrien return 16; 119484865Sobrien if (strstr (name, "[BSP]")) 119584865Sobrien return 17; 119684865Sobrien else if (strstr (name, "[BSPSTORE]")) 119784865Sobrien return 18; 119884865Sobrien else if (strstr (name, "[RNAT]")) 119984865Sobrien return 19; 120084865Sobrien else if (strstr (name, "[CCV]")) 120184865Sobrien return 32; 120284865Sobrien else if (strstr (name, "[ITC]")) 120384865Sobrien return 44; 120484865Sobrien else if (strstr (name, "[PFS]")) 120584865Sobrien return 64; 120684865Sobrien else if (strstr (name, "[LC]")) 120784865Sobrien return 65; 120884865Sobrien else if (strstr (name, "[EC]")) 120984865Sobrien return 66; 121084865Sobrien abort (); 121184865Sobrien case IA64_RS_CRX: 121284865Sobrien if (strstr (name, "[DCR]")) 121384865Sobrien return 0; 121484865Sobrien else if (strstr (name, "[ITM]")) 121584865Sobrien return 1; 121684865Sobrien else if (strstr (name, "[IVA]")) 121784865Sobrien return 2; 121884865Sobrien else if (strstr (name, "[PTA]")) 121984865Sobrien return 8; 122084865Sobrien else if (strstr (name, "[GPTA]")) 122184865Sobrien return 9; 122284865Sobrien else if (strstr (name, "[IPSR]")) 122384865Sobrien return 16; 122484865Sobrien else if (strstr (name, "[ISR]")) 122584865Sobrien return 17; 122684865Sobrien else if (strstr (name, "[IIP]")) 122784865Sobrien return 19; 122884865Sobrien else if (strstr (name, "[IFA]")) 122984865Sobrien return 20; 123084865Sobrien else if (strstr (name, "[ITIR]")) 123184865Sobrien return 21; 123284865Sobrien else if (strstr (name, "[IIPA]")) 123384865Sobrien return 22; 123484865Sobrien else if (strstr (name, "[IFS]")) 123584865Sobrien return 23; 123684865Sobrien else if (strstr (name, "[IIM]")) 123784865Sobrien return 24; 123884865Sobrien else if (strstr (name, "[IHA]")) 123984865Sobrien return 25; 124084865Sobrien else if (strstr (name, "[LID]")) 124184865Sobrien return 64; 124284865Sobrien else if (strstr (name, "[IVR]")) 124384865Sobrien return 65; 124484865Sobrien else if (strstr (name, "[TPR]")) 124584865Sobrien return 66; 124684865Sobrien else if (strstr (name, "[EOI]")) 124784865Sobrien return 67; 124884865Sobrien else if (strstr (name, "[ITV]")) 124984865Sobrien return 72; 125084865Sobrien else if (strstr (name, "[PMV]")) 125184865Sobrien return 73; 125284865Sobrien else if (strstr (name, "[CMCV]")) 125384865Sobrien return 74; 125484865Sobrien abort (); 125584865Sobrien case IA64_RS_PSR: 125684865Sobrien if (strstr (name, ".be")) 125784865Sobrien return 1; 125884865Sobrien else if (strstr (name, ".up")) 125984865Sobrien return 2; 126084865Sobrien else if (strstr (name, ".ac")) 126184865Sobrien return 3; 126284865Sobrien else if (strstr (name, ".mfl")) 126384865Sobrien return 4; 126484865Sobrien else if (strstr (name, ".mfh")) 126584865Sobrien return 5; 126684865Sobrien else if (strstr (name, ".ic")) 126784865Sobrien return 13; 126884865Sobrien else if (strstr (name, ".i")) 126984865Sobrien return 14; 127084865Sobrien else if (strstr (name, ".pk")) 127184865Sobrien return 15; 127284865Sobrien else if (strstr (name, ".dt")) 127384865Sobrien return 17; 127484865Sobrien else if (strstr (name, ".dfl")) 127584865Sobrien return 18; 127684865Sobrien else if (strstr (name, ".dfh")) 127784865Sobrien return 19; 127884865Sobrien else if (strstr (name, ".sp")) 127984865Sobrien return 20; 128084865Sobrien else if (strstr (name, ".pp")) 128184865Sobrien return 21; 128284865Sobrien else if (strstr (name, ".di")) 128384865Sobrien return 22; 128484865Sobrien else if (strstr (name, ".si")) 128584865Sobrien return 23; 128684865Sobrien else if (strstr (name, ".db")) 128784865Sobrien return 24; 128884865Sobrien else if (strstr (name, ".lp")) 128984865Sobrien return 25; 129084865Sobrien else if (strstr (name, ".tb")) 129184865Sobrien return 26; 129284865Sobrien else if (strstr (name, ".rt")) 129384865Sobrien return 27; 129484865Sobrien else if (strstr (name, ".cpl")) 129584865Sobrien return 32; 129684865Sobrien else if (strstr (name, ".rs")) 129784865Sobrien return 34; 129884865Sobrien else if (strstr (name, ".mc")) 129984865Sobrien return 35; 130084865Sobrien else if (strstr (name, ".it")) 130184865Sobrien return 36; 130284865Sobrien else if (strstr (name, ".id")) 130384865Sobrien return 37; 130484865Sobrien else if (strstr (name, ".da")) 130584865Sobrien return 38; 130684865Sobrien else if (strstr (name, ".dd")) 130784865Sobrien return 39; 130884865Sobrien else if (strstr (name, ".ss")) 130984865Sobrien return 40; 131084865Sobrien else if (strstr (name, ".ri")) 131184865Sobrien return 41; 131284865Sobrien else if (strstr (name, ".ed")) 131384865Sobrien return 43; 131484865Sobrien else if (strstr (name, ".bn")) 131584865Sobrien return 44; 131684865Sobrien else if (strstr (name, ".ia")) 131784865Sobrien return 45; 131884865Sobrien else 131984865Sobrien abort (); 132084865Sobrien default: 132184865Sobrien break; 132284865Sobrien } 132384865Sobrien return REG_NONE; 132484865Sobrien} 132584865Sobrien 132684865Sobrienstatic int 132784865Sobrienlookup_specifier (const char *name) 132884865Sobrien{ 132984865Sobrien if (strchr (name, '%')) 133084865Sobrien { 133184865Sobrien if (strstr (name, "AR[K%]") != NULL) 133284865Sobrien return IA64_RS_AR_K; 133384865Sobrien if (strstr (name, "AR[UNAT]") != NULL) 133484865Sobrien return IA64_RS_AR_UNAT; 133584865Sobrien if (strstr (name, "AR%, % in 8") != NULL) 133684865Sobrien return IA64_RS_AR; 133784865Sobrien if (strstr (name, "AR%, % in 48") != NULL) 133884865Sobrien return IA64_RS_ARb; 133984865Sobrien if (strstr (name, "BR%") != NULL) 134084865Sobrien return IA64_RS_BR; 134184865Sobrien if (strstr (name, "CR[IRR%]") != NULL) 134284865Sobrien return IA64_RS_CR_IRR; 134384865Sobrien if (strstr (name, "CR[LRR%]") != NULL) 134484865Sobrien return IA64_RS_CR_LRR; 134584865Sobrien if (strstr (name, "CR%") != NULL) 134684865Sobrien return IA64_RS_CR; 134784865Sobrien if (strstr (name, "FR%, % in 0") != NULL) 134884865Sobrien return IA64_RS_FR; 134984865Sobrien if (strstr (name, "FR%, % in 2") != NULL) 135084865Sobrien return IA64_RS_FRb; 135184865Sobrien if (strstr (name, "GR%") != NULL) 135284865Sobrien return IA64_RS_GR; 135384865Sobrien if (strstr (name, "PR%, % in 1 ") != NULL) 135484865Sobrien return IA64_RS_PR; 135584865Sobrien if (strstr (name, "PR%, % in 16 ") != NULL) 135684865Sobrien return IA64_RS_PRr; 135784865Sobrien 135884865Sobrien fprintf (stderr, "Warning! Don't know how to specify %% dependency %s\n", 135984865Sobrien name); 136084865Sobrien } 136184865Sobrien else if (strchr (name, '#')) 136284865Sobrien { 136384865Sobrien if (strstr (name, "CPUID#") != NULL) 136484865Sobrien return IA64_RS_CPUID; 136584865Sobrien if (strstr (name, "DBR#") != NULL) 136684865Sobrien return IA64_RS_DBR; 136784865Sobrien if (strstr (name, "IBR#") != NULL) 136884865Sobrien return IA64_RS_IBR; 136984865Sobrien if (strstr (name, "MSR#") != NULL) 137084865Sobrien return IA64_RS_MSR; 137184865Sobrien if (strstr (name, "PKR#") != NULL) 137284865Sobrien return IA64_RS_PKR; 137384865Sobrien if (strstr (name, "PMC#") != NULL) 137484865Sobrien return IA64_RS_PMC; 137584865Sobrien if (strstr (name, "PMD#") != NULL) 137684865Sobrien return IA64_RS_PMD; 137784865Sobrien if (strstr (name, "RR#") != NULL) 137884865Sobrien return IA64_RS_RR; 137984865Sobrien 138084865Sobrien fprintf (stderr, "Warning! Don't know how to specify # dependency %s\n", 138184865Sobrien name); 138284865Sobrien } 138384865Sobrien else if (strncmp (name, "AR[FPSR]", 8) == 0) 138484865Sobrien return IA64_RS_AR_FPSR; 138584865Sobrien else if (strncmp (name, "AR[", 3) == 0) 138684865Sobrien return IA64_RS_ARX; 138784865Sobrien else if (strncmp (name, "CR[", 3) == 0) 138884865Sobrien return IA64_RS_CRX; 138984865Sobrien else if (strncmp (name, "PSR.", 4) == 0) 139084865Sobrien return IA64_RS_PSR; 139184865Sobrien else if (strcmp (name, "InService*") == 0) 139284865Sobrien return IA64_RS_INSERVICE; 139384865Sobrien else if (strcmp (name, "GR0") == 0) 139484865Sobrien return IA64_RS_GR0; 139584865Sobrien else if (strcmp (name, "CFM") == 0) 139684865Sobrien return IA64_RS_CFM; 139784865Sobrien else if (strcmp (name, "PR63") == 0) 139884865Sobrien return IA64_RS_PR63; 139984865Sobrien else if (strcmp (name, "RSE") == 0) 140084865Sobrien return IA64_RS_RSE; 140184865Sobrien 140284865Sobrien return IA64_RS_ANY; 140384865Sobrien} 140484865Sobrien 140584865Sobrienvoid 140684865Sobrienprint_dependency_table () 140784865Sobrien{ 140884865Sobrien int i, j; 140984865Sobrien 141084865Sobrien if (debug) 141184865Sobrien { 141284865Sobrien for (i=0;i < iclen;i++) 141384865Sobrien { 141484865Sobrien if (ics[i]->is_class) 141584865Sobrien { 141684865Sobrien if (!ics[i]->nsubs) 141784865Sobrien { 141884865Sobrien fprintf (stderr, "Warning: IC:%s", ics[i]->name); 141984865Sobrien if (ics[i]->comment) 142084865Sobrien fprintf (stderr, "[%s]", ics[i]->comment); 142184865Sobrien fprintf (stderr, " has no terminals or sub-classes\n"); 142284865Sobrien } 142384865Sobrien } 142484865Sobrien else 142584865Sobrien { 142684865Sobrien if (!ics[i]->terminal_resolved && !ics[i]->orphan) 142784865Sobrien { 142884865Sobrien fprintf(stderr, "Warning: no insns mapped directly to " 142984865Sobrien "terminal IC %s", ics[i]->name); 143084865Sobrien if (ics[i]->comment) 143184865Sobrien fprintf(stderr, "[%s] ", ics[i]->comment); 143284865Sobrien fprintf(stderr, "\n"); 143384865Sobrien } 143484865Sobrien } 143584865Sobrien } 143684865Sobrien 143784865Sobrien for (i=0;i < iclen;i++) 143884865Sobrien { 143984865Sobrien if (ics[i]->orphan) 144084865Sobrien { 144184865Sobrien mark_used (ics[i], 1); 144284865Sobrien fprintf (stderr, "Warning: class %s is defined but not used\n", 144384865Sobrien ics[i]->name); 144484865Sobrien } 144584865Sobrien } 144684865Sobrien 144784865Sobrien if (debug > 1) for (i=0;i < rdepslen;i++) 144884865Sobrien { 144984865Sobrien static const char *mode_str[] = { "RAW", "WAW", "WAR" }; 145084865Sobrien if (rdeps[i]->total_chks == 0) 145184865Sobrien { 145284865Sobrien fprintf (stderr, "Warning: rsrc %s (%s) has no chks%s\n", 145384865Sobrien rdeps[i]->name, mode_str[rdeps[i]->mode], 145484865Sobrien rdeps[i]->total_regs ? "" : " or regs"); 145584865Sobrien } 145684865Sobrien else if (rdeps[i]->total_regs == 0) 145784865Sobrien { 145884865Sobrien fprintf (stderr, "Warning: rsrc %s (%s) has no regs\n", 145984865Sobrien rdeps[i]->name, mode_str[rdeps[i]->mode]); 146084865Sobrien } 146184865Sobrien } 146284865Sobrien } 146384865Sobrien 146484865Sobrien /* the dependencies themselves */ 146584865Sobrien printf ("static const struct ia64_dependency\ndependencies[] = {\n"); 146684865Sobrien for (i=0;i < rdepslen;i++) 146784865Sobrien { 146884865Sobrien /* '%', '#', AR[], CR[], or PSR. indicates we need to specify the actual 146984865Sobrien resource used */ 147084865Sobrien int specifier = lookup_specifier (rdeps[i]->name); 147184865Sobrien int regindex = lookup_regindex (rdeps[i]->name, specifier); 147284865Sobrien 147384865Sobrien printf (" { \"%s\", %d, %d, %d, %d, ", 147484865Sobrien rdeps[i]->name, specifier, 147584865Sobrien (int)rdeps[i]->mode, (int)rdeps[i]->semantics, regindex); 147684865Sobrien if (rdeps[i]->semantics == IA64_DVS_OTHER) 147784865Sobrien printf ("\"%s\", ", rdeps[i]->extra); 147884865Sobrien else 147984865Sobrien printf ("NULL, "); 148084865Sobrien printf("},\n"); 148184865Sobrien } 148284865Sobrien printf ("};\n\n"); 148384865Sobrien 148484865Sobrien /* and dependency lists */ 148584865Sobrien for (i=0;i < dlistlen;i++) 148684865Sobrien { 148784865Sobrien int len = 2; 148884865Sobrien printf ("static const short dep%d[] = {\n ", i); 148984865Sobrien for (j=0;j < dlists[i]->len; j++) 149084865Sobrien { 149184865Sobrien len += printf ("%d, ", dlists[i]->deps[j]); 149284865Sobrien if (len > 75) 149384865Sobrien { 149484865Sobrien printf("\n "); 149584865Sobrien len = 2; 149684865Sobrien } 149784865Sobrien } 149884865Sobrien printf ("\n};\n\n"); 149984865Sobrien } 150084865Sobrien 150184865Sobrien /* and opcode dependency list */ 150284865Sobrien printf ("#define NELS(X) (sizeof(X)/sizeof(X[0]))\n"); 150384865Sobrien printf ("static const struct ia64_opcode_dependency\n"); 150484865Sobrien printf ("op_dependencies[] = {\n"); 150584865Sobrien for (i=0;i < opdeplen;i++) 150684865Sobrien { 150784865Sobrien printf (" { "); 150884865Sobrien if (opdeps[i]->chk == -1) 150984865Sobrien printf ("0, NULL, "); 151084865Sobrien else 151184865Sobrien printf ("NELS(dep%d), dep%d, ", opdeps[i]->chk, opdeps[i]->chk); 151284865Sobrien if (opdeps[i]->reg == -1) 151384865Sobrien printf ("0, NULL, "); 151484865Sobrien else 151584865Sobrien printf ("NELS(dep%d), dep%d, ", opdeps[i]->reg, opdeps[i]->reg); 151684865Sobrien printf ("},\n"); 151784865Sobrien } 151884865Sobrien printf ("};\n\n"); 151984865Sobrien} 152084865Sobrien 152184865Sobrien 152284865Sobrien/* Add STR to the string table. */ 152384865Sobrien 152484865Sobrienstatic struct string_entry * 152584865Sobrieninsert_string (str) 152684865Sobrien char *str; 152784865Sobrien{ 152884865Sobrien int start = 0, end = strtablen; 152984865Sobrien int i, x; 153084865Sobrien 153184865Sobrien if (strtablen == strtabtotlen) 153284865Sobrien { 153384865Sobrien strtabtotlen += 20; 153484865Sobrien string_table = (struct string_entry **) 153584865Sobrien xrealloc (string_table, 153684865Sobrien sizeof (struct string_entry **) * strtabtotlen); 153784865Sobrien } 153884865Sobrien 153984865Sobrien if (strtablen == 0) 154084865Sobrien { 154184865Sobrien strtablen = 1; 154284865Sobrien string_table[0] = tmalloc (struct string_entry); 154384865Sobrien string_table[0]->s = xstrdup (str); 154484865Sobrien string_table[0]->num = 0; 154584865Sobrien return string_table[0]; 154684865Sobrien } 154784865Sobrien 154884865Sobrien if (strcmp (str, string_table[strtablen - 1]->s) > 0) 154984865Sobrien { 155084865Sobrien i = end; 155184865Sobrien } 155284865Sobrien else if (strcmp (str, string_table[0]->s) < 0) 155384865Sobrien { 155484865Sobrien i = 0; 155584865Sobrien } 155684865Sobrien else 155784865Sobrien { 155884865Sobrien while (1) 155984865Sobrien { 156084865Sobrien int c; 156184865Sobrien 156284865Sobrien i = (start + end) / 2; 156384865Sobrien c = strcmp (str, string_table[i]->s); 156484865Sobrien if (c < 0) 156584865Sobrien { 156684865Sobrien end = i - 1; 156784865Sobrien } 156884865Sobrien else if (c == 0) 156984865Sobrien { 157084865Sobrien return string_table[i]; 157184865Sobrien } 157284865Sobrien else 157384865Sobrien { 157484865Sobrien start = i + 1; 157584865Sobrien } 157684865Sobrien if (start > end) 157784865Sobrien { 157884865Sobrien break; 157984865Sobrien } 158084865Sobrien } 158184865Sobrien } 158284865Sobrien for (; i > 0 && i < strtablen; i--) 158384865Sobrien { 158484865Sobrien if (strcmp (str, string_table[i - 1]->s) > 0) 158584865Sobrien { 158684865Sobrien break; 158784865Sobrien } 158884865Sobrien } 158984865Sobrien for (; i < strtablen; i++) 159084865Sobrien { 159184865Sobrien if (strcmp (str, string_table[i]->s) < 0) 159284865Sobrien { 159384865Sobrien break; 159484865Sobrien } 159584865Sobrien } 159684865Sobrien for (x = strtablen - 1; x >= i; x--) 159784865Sobrien { 159884865Sobrien string_table[x + 1] = string_table[x]; 159984865Sobrien string_table[x + 1]->num = x + 1; 160084865Sobrien } 160184865Sobrien string_table[i] = tmalloc (struct string_entry); 160284865Sobrien string_table[i]->s = xstrdup (str); 160384865Sobrien string_table[i]->num = i; 160484865Sobrien strtablen++; 160584865Sobrien return string_table[i]; 160684865Sobrien} 160784865Sobrien 160884865Sobrienstruct bittree * 160984865Sobrienmake_bittree_entry () 161084865Sobrien{ 161184865Sobrien struct bittree *res = tmalloc (struct bittree); 161284865Sobrien 161384865Sobrien res->disent = NULL; 161484865Sobrien res->bits[0] = NULL; 161584865Sobrien res->bits[1] = NULL; 161684865Sobrien res->bits[2] = NULL; 161784865Sobrien res->skip_flag = 0; 161884865Sobrien res->bits_to_skip = 0; 161984865Sobrien return res; 162084865Sobrien} 162184865Sobrien 162284865Sobrienstruct disent * 162384865Sobrienadd_dis_table_ent (which, insn, order, completer_index) 162484865Sobrien struct disent *which; 162584865Sobrien int insn; 162684865Sobrien int order; 162784865Sobrien int completer_index; 162884865Sobrien{ 162984865Sobrien int ci = 0; 163084865Sobrien struct disent *ent; 163184865Sobrien 163284865Sobrien if (which != NULL) 163384865Sobrien { 163484865Sobrien ent = which; 163584865Sobrien 163684865Sobrien ent->nextcnt++; 163784865Sobrien while (ent->nexte != NULL) 163884865Sobrien { 163984865Sobrien ent = ent->nexte; 164084865Sobrien } 164184865Sobrien ent = (ent->nexte = tmalloc (struct disent)); 164284865Sobrien } 164384865Sobrien else 164484865Sobrien { 164584865Sobrien ent = tmalloc (struct disent); 164684865Sobrien ent->next_ent = disinsntable; 164784865Sobrien disinsntable = ent; 164884865Sobrien which = ent; 164984865Sobrien } 165084865Sobrien ent->nextcnt = 0; 165184865Sobrien ent->nexte = NULL; 165284865Sobrien ent->insn = insn; 165384865Sobrien ent->priority = order; 165484865Sobrien 165584865Sobrien while (completer_index != 1) 165684865Sobrien { 165784865Sobrien ci = (ci << 1) | (completer_index & 1); 165884865Sobrien completer_index >>= 1; 165984865Sobrien } 166084865Sobrien ent->completer_index = ci; 166184865Sobrien return which; 166284865Sobrien} 166384865Sobrien 166484865Sobrienvoid 166584865Sobrienfinish_distable () 166684865Sobrien{ 166784865Sobrien struct disent *ent = disinsntable; 166884865Sobrien struct disent *prev = ent; 166984865Sobrien 167084865Sobrien ent->ournum = 32768; 167184865Sobrien while ((ent = ent->next_ent) != NULL) 167284865Sobrien { 167384865Sobrien ent->ournum = prev->ournum + prev->nextcnt + 1; 167484865Sobrien prev = ent; 167584865Sobrien } 167684865Sobrien} 167784865Sobrien 167884865Sobrienvoid 167984865Sobrieninsert_bit_table_ent (curr_ent, bit, opcode, mask, 168084865Sobrien opcodenum, order, completer_index) 168184865Sobrien struct bittree *curr_ent; 168284865Sobrien int bit; 168384865Sobrien ia64_insn opcode; 168484865Sobrien ia64_insn mask; 168584865Sobrien int opcodenum; 168684865Sobrien int order; 168784865Sobrien int completer_index; 168884865Sobrien{ 168984865Sobrien ia64_insn m; 169084865Sobrien int b; 169184865Sobrien struct bittree *next; 169284865Sobrien 169384865Sobrien if (bit == -1) 169484865Sobrien { 169584865Sobrien struct disent *nent = add_dis_table_ent (curr_ent->disent, 169684865Sobrien opcodenum, order, 169784865Sobrien completer_index); 169884865Sobrien curr_ent->disent = nent; 169984865Sobrien return; 170084865Sobrien } 170184865Sobrien 170284865Sobrien m = ((ia64_insn) 1) << bit; 170384865Sobrien 170484865Sobrien if (mask & m) 170584865Sobrien { 170684865Sobrien b = (opcode & m) ? 1 : 0; 170784865Sobrien } 170884865Sobrien else 170984865Sobrien { 171084865Sobrien b = 2; 171184865Sobrien } 171284865Sobrien next = curr_ent->bits[b]; 171384865Sobrien if (next == NULL) 171484865Sobrien { 171584865Sobrien next = make_bittree_entry (); 171684865Sobrien curr_ent->bits[b] = next; 171784865Sobrien } 171884865Sobrien insert_bit_table_ent (next, bit - 1, opcode, mask, opcodenum, order, 171984865Sobrien completer_index); 172084865Sobrien} 172184865Sobrien 172284865Sobrienvoid 172384865Sobrienadd_dis_entry (first, opcode, mask, opcodenum, ent, completer_index) 172484865Sobrien struct bittree *first; 172584865Sobrien ia64_insn opcode; 172684865Sobrien ia64_insn mask; 172784865Sobrien int opcodenum; 172884865Sobrien struct completer_entry *ent; 172984865Sobrien int completer_index; 173084865Sobrien{ 173184865Sobrien if (completer_index & (1 << 20)) 173284865Sobrien { 173384865Sobrien abort (); 173484865Sobrien } 173584865Sobrien 173684865Sobrien while (ent != NULL) 173784865Sobrien { 173884865Sobrien ia64_insn newopcode = (opcode & (~ ent->mask)) | ent->bits; 173984865Sobrien add_dis_entry (first, newopcode, mask, opcodenum, ent->addl_entries, 174084865Sobrien (completer_index << 1) | 1); 174184865Sobrien if (ent->is_terminal) 174284865Sobrien { 174384865Sobrien insert_bit_table_ent (bittree, 40, newopcode, mask, 174484865Sobrien opcodenum, opcode_count - ent->order - 1, 174584865Sobrien (completer_index << 1) | 1); 174684865Sobrien } 174784865Sobrien completer_index <<= 1; 174884865Sobrien ent = ent->alternative; 174984865Sobrien } 175084865Sobrien} 175184865Sobrien 175284865Sobrien/* This optimization pass combines multiple "don't care" nodes. */ 175384865Sobrienvoid 175484865Sobriencompact_distree (ent) 175584865Sobrien struct bittree *ent; 175684865Sobrien{ 175784865Sobrien#define IS_SKIP(ent) \ 175884865Sobrien ((ent->bits[2] !=NULL) \ 175984865Sobrien && (ent->bits[0] == NULL && ent->bits[1] == NULL && ent->skip_flag == 0)) 176084865Sobrien 176184865Sobrien int bitcnt = 0; 176284865Sobrien struct bittree *nent = ent; 176384865Sobrien int x; 176484865Sobrien 176584865Sobrien while (IS_SKIP (nent)) 176684865Sobrien { 176784865Sobrien bitcnt++; 176884865Sobrien nent = nent->bits[2]; 176984865Sobrien } 177084865Sobrien 177184865Sobrien if (bitcnt) 177284865Sobrien { 177384865Sobrien struct bittree *next = ent->bits[2]; 177484865Sobrien 177584865Sobrien ent->bits[0] = nent->bits[0]; 177684865Sobrien ent->bits[1] = nent->bits[1]; 177784865Sobrien ent->bits[2] = nent->bits[2]; 177884865Sobrien ent->disent = nent->disent; 177984865Sobrien ent->skip_flag = 1; 178084865Sobrien ent->bits_to_skip = bitcnt; 178184865Sobrien while (next != nent) 178284865Sobrien { 178384865Sobrien struct bittree *b = next; 178484865Sobrien next = next->bits[2]; 178584865Sobrien free (b); 178684865Sobrien } 178784865Sobrien free (nent); 178884865Sobrien } 178984865Sobrien 179084865Sobrien for (x = 0; x < 3; x++) 179184865Sobrien { 179284865Sobrien struct bittree *i = ent->bits[x]; 179384865Sobrien if (i != NULL) 179484865Sobrien { 179584865Sobrien compact_distree (i); 179684865Sobrien } 179784865Sobrien } 179884865Sobrien} 179984865Sobrien 180084865Sobrienstatic unsigned char *insn_list; 180184865Sobrienstatic int insn_list_len = 0; 180284865Sobrienstatic int tot_insn_list_len = 0; 180384865Sobrien 180484865Sobrien/* Generate the disassembler state machine corresponding to the tree 180584865Sobrien in ENT. */ 180684865Sobrienvoid 180784865Sobriengen_dis_table (ent) 180884865Sobrien struct bittree *ent; 180984865Sobrien{ 181084865Sobrien int x; 181184865Sobrien int our_offset = insn_list_len; 181284865Sobrien int bitsused = 5; 181384865Sobrien int totbits = bitsused; 181484865Sobrien int needed_bytes; 181584865Sobrien int zero_count = 0; 181684865Sobrien int zero_dest = 0; /* initialize this with 0 to keep gcc quiet... */ 181784865Sobrien 181884865Sobrien /* If this is a terminal entry, there's no point in skipping any 181984865Sobrien bits. */ 182084865Sobrien if (ent->skip_flag && ent->bits[0] == NULL && ent->bits[1] == NULL && 182184865Sobrien ent->bits[2] == NULL) 182284865Sobrien { 182384865Sobrien if (ent->disent == NULL) 182484865Sobrien { 182584865Sobrien abort (); 182684865Sobrien } 182784865Sobrien else 182884865Sobrien { 182984865Sobrien ent->skip_flag = 0; 183084865Sobrien } 183184865Sobrien } 183284865Sobrien 183384865Sobrien /* Calculate the amount of space needed for this entry, or at least 183484865Sobrien a conservatively large approximation. */ 183584865Sobrien if (ent->skip_flag) 183684865Sobrien { 183784865Sobrien totbits += 5; 183884865Sobrien } 183984865Sobrien for (x = 1; x < 3; x++) 184084865Sobrien { 184184865Sobrien if (ent->bits[x] != NULL) 184284865Sobrien { 184384865Sobrien totbits += 16; 184484865Sobrien } 184584865Sobrien } 184684865Sobrien 184784865Sobrien if (ent->disent != NULL) 184884865Sobrien { 184984865Sobrien if (ent->bits[2] != NULL) 185084865Sobrien { 185184865Sobrien abort (); 185284865Sobrien } 185384865Sobrien totbits += 16; 185484865Sobrien } 185584865Sobrien 185684865Sobrien /* Now allocate the space. */ 185784865Sobrien needed_bytes = (totbits + 7) / 8; 185884865Sobrien if ((needed_bytes + insn_list_len) > tot_insn_list_len) 185984865Sobrien { 186084865Sobrien tot_insn_list_len += 256; 186184865Sobrien insn_list = (char *) xrealloc (insn_list, tot_insn_list_len); 186284865Sobrien } 186384865Sobrien our_offset = insn_list_len; 186484865Sobrien insn_list_len += needed_bytes; 186584865Sobrien memset (insn_list + our_offset, 0, needed_bytes); 186684865Sobrien 186784865Sobrien /* Encode the skip entry by setting bit 6 set in the state op field, 186884865Sobrien and store the # of bits to skip immediately after. */ 186984865Sobrien if (ent->skip_flag) 187084865Sobrien { 187184865Sobrien bitsused += 5; 187284865Sobrien insn_list[our_offset + 0] |= 0x40 | ((ent->bits_to_skip >> 2) & 0xf); 187384865Sobrien insn_list[our_offset + 1] |= ((ent->bits_to_skip & 3) << 6); 187484865Sobrien } 187584865Sobrien 187684865Sobrien#define IS_ONLY_IFZERO(ENT) \ 187784865Sobrien ((ENT)->bits[0] != NULL && (ENT)->bits[1] == NULL && (ENT)->bits[2] == NULL \ 187884865Sobrien && (ENT)->disent == NULL && (ENT)->skip_flag == 0) 187984865Sobrien 188084865Sobrien /* Store an "if (bit is zero)" instruction by setting bit 7 in the 188184865Sobrien state op field. */ 188284865Sobrien 188384865Sobrien if (ent->bits[0] != NULL) 188484865Sobrien { 188584865Sobrien struct bittree *nent = ent->bits[0]; 188684865Sobrien zero_count = 0; 188784865Sobrien 188884865Sobrien insn_list[our_offset] |= 0x80; 188984865Sobrien 189084865Sobrien /* We can encode sequences of multiple "if (bit is zero)" tests 189184865Sobrien by storing the # of zero bits to check in the lower 3 bits of 189284865Sobrien the instruction. However, this only applies if the state 189384865Sobrien solely tests for a zero bit. */ 189484865Sobrien 189584865Sobrien if (IS_ONLY_IFZERO (ent)) 189684865Sobrien { 189784865Sobrien while (IS_ONLY_IFZERO (nent) && zero_count < 7) 189884865Sobrien { 189984865Sobrien nent = nent->bits[0]; 190084865Sobrien zero_count++; 190184865Sobrien } 190284865Sobrien 190384865Sobrien insn_list[our_offset + 0] |= zero_count; 190484865Sobrien } 190584865Sobrien zero_dest = insn_list_len; 190684865Sobrien gen_dis_table (nent); 190784865Sobrien } 190884865Sobrien 190984865Sobrien /* Now store the remaining tests. We also handle a sole "termination 191084865Sobrien entry" by storing it as an "any bit" test. */ 191184865Sobrien 191284865Sobrien for (x = 1; x < 3; x++) 191384865Sobrien { 191484865Sobrien if (ent->bits[x] != NULL || (x == 2 && ent->disent != NULL)) 191584865Sobrien { 191684865Sobrien struct bittree *i = ent->bits[x]; 191784865Sobrien int idest; 191884865Sobrien int currbits = 15; 191984865Sobrien 192084865Sobrien if (i != NULL) 192184865Sobrien { 192284865Sobrien /* If the instruction being branched to only consists of 192384865Sobrien a termination entry, use the termination entry as the 192484865Sobrien place to branch to instead. */ 192584865Sobrien if (i->bits[0] == NULL && i->bits[1] == NULL 192684865Sobrien && i->bits[2] == NULL && i->disent != NULL) 192784865Sobrien { 192884865Sobrien idest = i->disent->ournum; 192984865Sobrien i = NULL; 193084865Sobrien } 193184865Sobrien else 193284865Sobrien { 193384865Sobrien idest = insn_list_len - our_offset; 193484865Sobrien } 193584865Sobrien } 193684865Sobrien else 193784865Sobrien { 193884865Sobrien idest = ent->disent->ournum; 193984865Sobrien } 194084865Sobrien 194184865Sobrien /* If the destination offset for the if (bit is 1) test is less 194284865Sobrien than 256 bytes away, we can store it as 8-bits instead of 16; 194384865Sobrien the instruction has bit 5 set for the 16-bit address, and bit 194484865Sobrien 4 for the 8-bit address. Since we've already allocated 16 194584865Sobrien bits for the address we need to deallocate the space. 194684865Sobrien 194784865Sobrien Note that branchings within the table are relative, and 194884865Sobrien there are no branches that branch past our instruction yet 194984865Sobrien so we do not need to adjust any other offsets. */ 195084865Sobrien 195184865Sobrien if (x == 1) 195284865Sobrien { 195384865Sobrien if (idest <= 256) 195484865Sobrien { 195584865Sobrien int start = our_offset + bitsused / 8 + 1; 195684865Sobrien 195784865Sobrien memmove (insn_list + start, 195884865Sobrien insn_list + start + 1, 195984865Sobrien insn_list_len - (start + 1)); 196084865Sobrien currbits = 7; 196184865Sobrien totbits -= 8; 196284865Sobrien needed_bytes--; 196384865Sobrien insn_list_len--; 196484865Sobrien insn_list[our_offset] |= 0x10; 196584865Sobrien idest--; 196684865Sobrien } 196784865Sobrien else 196884865Sobrien { 196984865Sobrien insn_list[our_offset] |= 0x20; 197084865Sobrien } 197184865Sobrien } 197284865Sobrien else 197384865Sobrien { 197484865Sobrien /* An instruction which solely consists of a termination 197584865Sobrien marker and whose disassembly name index is < 4096 197684865Sobrien can be stored in 16 bits. The encoding is slightly 197784865Sobrien odd; the upper 4 bits of the instruction are 0x3, and 197884865Sobrien bit 3 loses its normal meaning. */ 197984865Sobrien 198084865Sobrien if (ent->bits[0] == NULL && ent->bits[1] == NULL 198184865Sobrien && ent->bits[2] == NULL && ent->skip_flag == 0 198284865Sobrien && ent->disent != NULL 198384865Sobrien && ent->disent->ournum < (32768 + 4096)) 198484865Sobrien { 198584865Sobrien int start = our_offset + bitsused / 8 + 1; 198684865Sobrien 198784865Sobrien memmove (insn_list + start, 198884865Sobrien insn_list + start + 1, 198984865Sobrien insn_list_len - (start + 1)); 199084865Sobrien currbits = 11; 199184865Sobrien totbits -= 5; 199284865Sobrien bitsused--; 199384865Sobrien needed_bytes--; 199484865Sobrien insn_list_len--; 199584865Sobrien insn_list[our_offset] |= 0x30; 199684865Sobrien idest &= ~32768; 199784865Sobrien } 199884865Sobrien else 199984865Sobrien { 200084865Sobrien insn_list[our_offset] |= 0x08; 200184865Sobrien } 200284865Sobrien } 200384865Sobrien if (debug) 200484865Sobrien { 200584865Sobrien int id = idest; 200684865Sobrien 200784865Sobrien if (i == NULL) 200884865Sobrien { 200984865Sobrien id |= 32768; 201084865Sobrien } 201184865Sobrien else if (! (id & 32768)) 201284865Sobrien { 201384865Sobrien id += our_offset; 201484865Sobrien } 201584865Sobrien if (x == 1) 201684865Sobrien { 201784865Sobrien printf ("%d: if (1) goto %d\n", our_offset, id); 201884865Sobrien } 201984865Sobrien else 202084865Sobrien { 202184865Sobrien printf ("%d: try %d\n", our_offset, id); 202284865Sobrien } 202384865Sobrien } 202484865Sobrien 202584865Sobrien /* Store the address of the entry being branched to. */ 202684865Sobrien while (currbits >= 0) 202784865Sobrien { 202884865Sobrien char *byte = insn_list + our_offset + bitsused / 8; 202984865Sobrien 203084865Sobrien if (idest & (1 << currbits)) 203184865Sobrien { 203284865Sobrien *byte |= (1 << (7 - (bitsused % 8))); 203384865Sobrien } 203484865Sobrien bitsused++; 203584865Sobrien currbits--; 203684865Sobrien } 203784865Sobrien 203884865Sobrien /* Now generate the states for the entry being branched to. */ 203984865Sobrien if (i != NULL) 204084865Sobrien { 204184865Sobrien gen_dis_table (i); 204284865Sobrien } 204384865Sobrien 204484865Sobrien } 204584865Sobrien } 204684865Sobrien if (debug) 204784865Sobrien { 204884865Sobrien if (ent->skip_flag) 204984865Sobrien { 205084865Sobrien printf ("%d: skipping %d\n", our_offset, ent->bits_to_skip); 205184865Sobrien } 205284865Sobrien 205384865Sobrien if (ent->bits[0] != NULL) 205484865Sobrien { 205584865Sobrien printf ("%d: if (0:%d) goto %d\n", our_offset, zero_count + 1, 205684865Sobrien zero_dest); 205784865Sobrien } 205884865Sobrien } 205984865Sobrien if (bitsused != totbits) 206084865Sobrien { 206184865Sobrien abort (); 206284865Sobrien } 206384865Sobrien} 206484865Sobrien 206584865Sobrienvoid 206684865Sobrienprint_dis_table () 206784865Sobrien{ 206884865Sobrien int x; 206984865Sobrien struct disent *cent = disinsntable; 207084865Sobrien 207184865Sobrien printf ("static const char dis_table[] = {\n"); 207284865Sobrien for (x = 0; x < insn_list_len; x++) 207384865Sobrien { 207484865Sobrien if ((x > 0) && ((x % 12) == 0)) 207584865Sobrien { 207684865Sobrien printf ("\n"); 207784865Sobrien } 207884865Sobrien printf ("0x%02x, ", insn_list[x]); 207984865Sobrien } 208084865Sobrien printf ("\n};\n\n"); 208184865Sobrien 208284865Sobrien printf ("static const struct ia64_dis_names ia64_dis_names[] = {\n"); 208384865Sobrien while (cent != NULL) 208484865Sobrien { 208584865Sobrien struct disent *ent = cent; 208684865Sobrien 208784865Sobrien while (ent != NULL) 208884865Sobrien { 208984865Sobrien printf ("{ 0x%x, %d, %d, %d },\n", ent->completer_index, 209084865Sobrien ent->insn, (ent->nexte != NULL ? 1 : 0), 209184865Sobrien ent->priority); 209284865Sobrien ent = ent->nexte; 209384865Sobrien } 209484865Sobrien cent = cent->next_ent; 209584865Sobrien } 209684865Sobrien printf ("};\n\n"); 209784865Sobrien} 209884865Sobrien 209984865Sobrienvoid 210084865Sobriengenerate_disassembler () 210184865Sobrien{ 210284865Sobrien int i; 210384865Sobrien 210484865Sobrien bittree = make_bittree_entry (); 210584865Sobrien 210684865Sobrien for (i=0; i < otlen;i++) 210784865Sobrien { 210884865Sobrien struct main_entry *ptr = ordered_table[i]; 210984865Sobrien 211084865Sobrien if (ptr->opcode->type != IA64_TYPE_DYN) 211184865Sobrien { 211284865Sobrien add_dis_entry (bittree, 211384865Sobrien ptr->opcode->opcode, ptr->opcode->mask, 211484865Sobrien ptr->main_index, 211584865Sobrien ptr->completers, 1); 211684865Sobrien } 211784865Sobrien } 211884865Sobrien 211984865Sobrien compact_distree (bittree); 212084865Sobrien finish_distable (); 212184865Sobrien gen_dis_table (bittree); 212284865Sobrien 212384865Sobrien print_dis_table (); 212484865Sobrien} 212584865Sobrien 212684865Sobrienvoid 212784865Sobrienprint_string_table () 212884865Sobrien{ 212984865Sobrien int x; 213084865Sobrien char lbuf[80], buf[80]; 213184865Sobrien int blen = 0; 213284865Sobrien 213384865Sobrien printf ("static const char *ia64_strings[] = {\n"); 213484865Sobrien lbuf[0] = '\0'; 213584865Sobrien for (x = 0; x < strtablen; x++) 213684865Sobrien { 213784865Sobrien int len; 213884865Sobrien 213984865Sobrien if (strlen (string_table[x]->s) > 75) 214084865Sobrien { 214184865Sobrien abort (); 214284865Sobrien } 214384865Sobrien sprintf (buf, " \"%s\",", string_table[x]->s); 214484865Sobrien len = strlen (buf); 214584865Sobrien if ((blen + len) > 75) 214684865Sobrien { 214784865Sobrien printf (" %s\n", lbuf); 214884865Sobrien lbuf[0] = '\0'; 214984865Sobrien blen = 0; 215084865Sobrien } 215184865Sobrien strcat (lbuf, buf); 215284865Sobrien blen += len; 215384865Sobrien } 215484865Sobrien if (blen > 0) 215584865Sobrien { 215684865Sobrien printf (" %s\n", lbuf); 215784865Sobrien } 215884865Sobrien printf ("};\n\n"); 215984865Sobrien} 216084865Sobrien 216184865Sobrienstatic struct completer_entry **glist; 216284865Sobrienstatic int glistlen = 0; 216384865Sobrienstatic int glisttotlen = 0; 216484865Sobrien 216584865Sobrien/* If the completer trees ENT1 and ENT2 are equal, return 1. */ 216684865Sobrien 216784865Sobrienint 216884865Sobriencompleter_entries_eq (ent1, ent2) 216984865Sobrien struct completer_entry *ent1, *ent2; 217084865Sobrien{ 217184865Sobrien while (ent1 != NULL && ent2 != NULL) 217284865Sobrien { 217384865Sobrien if (ent1->name->num != ent2->name->num 217484865Sobrien || ent1->bits != ent2->bits 217584865Sobrien || ent1->mask != ent2->mask 217684865Sobrien || ent1->is_terminal != ent2->is_terminal 217784865Sobrien || ent1->dependencies != ent2->dependencies 217884865Sobrien || ent1->order != ent2->order) 217984865Sobrien { 218084865Sobrien return 0; 218184865Sobrien } 218284865Sobrien if (! completer_entries_eq (ent1->addl_entries, ent2->addl_entries)) 218384865Sobrien { 218484865Sobrien return 0; 218584865Sobrien } 218684865Sobrien ent1 = ent1->alternative; 218784865Sobrien ent2 = ent2->alternative; 218884865Sobrien } 218984865Sobrien return ent1 == ent2; 219084865Sobrien} 219184865Sobrien 219284865Sobrien/* Insert ENT into the global list of completers and return it. If an 219384865Sobrien equivalent entry (according to completer_entries_eq) already exists, 219484865Sobrien it is returned instead. */ 219584865Sobrienstruct completer_entry * 219684865Sobrieninsert_gclist (ent) 219784865Sobrien struct completer_entry *ent; 219884865Sobrien{ 219984865Sobrien if (ent != NULL) 220084865Sobrien { 220184865Sobrien int i; 220284865Sobrien int x; 220384865Sobrien int start = 0, end; 220484865Sobrien 220584865Sobrien ent->addl_entries = insert_gclist (ent->addl_entries); 220684865Sobrien ent->alternative = insert_gclist (ent->alternative); 220784865Sobrien 220884865Sobrien i = glistlen / 2; 220984865Sobrien end = glistlen; 221084865Sobrien 221184865Sobrien if (glisttotlen == glistlen) 221284865Sobrien { 221384865Sobrien glisttotlen += 20; 221484865Sobrien glist = (struct completer_entry **) 221584865Sobrien xrealloc (glist, sizeof (struct completer_entry *) * glisttotlen); 221684865Sobrien } 221784865Sobrien 221884865Sobrien if (glistlen == 0) 221984865Sobrien { 222084865Sobrien glist[0] = ent; 222184865Sobrien glistlen = 1; 222284865Sobrien return ent; 222384865Sobrien } 222484865Sobrien 222584865Sobrien if (ent->name->num < glist[0]->name->num) 222684865Sobrien { 222784865Sobrien i = 0; 222884865Sobrien } 222984865Sobrien else if (ent->name->num > glist[end - 1]->name->num) 223084865Sobrien { 223184865Sobrien i = end; 223284865Sobrien } 223384865Sobrien else 223484865Sobrien { 223584865Sobrien int c; 223684865Sobrien 223784865Sobrien while (1) 223884865Sobrien { 223984865Sobrien i = (start + end) / 2; 224084865Sobrien c = ent->name->num - glist[i]->name->num; 224184865Sobrien if (c < 0) 224284865Sobrien { 224384865Sobrien end = i - 1; 224484865Sobrien } 224584865Sobrien else if (c == 0) 224684865Sobrien { 224784865Sobrien while (i > 0 224884865Sobrien && ent->name->num == glist[i - 1]->name->num) 224984865Sobrien { 225084865Sobrien i--; 225184865Sobrien } 225284865Sobrien break; 225384865Sobrien } 225484865Sobrien else 225584865Sobrien { 225684865Sobrien start = i + 1; 225784865Sobrien } 225884865Sobrien if (start > end) 225984865Sobrien { 226084865Sobrien break; 226184865Sobrien } 226284865Sobrien } 226384865Sobrien if (c == 0) 226484865Sobrien { 226584865Sobrien while (i < glistlen) 226684865Sobrien { 226784865Sobrien if (ent->name->num != glist[i]->name->num) 226884865Sobrien { 226984865Sobrien break; 227084865Sobrien } 227184865Sobrien if (completer_entries_eq (ent, glist[i])) 227284865Sobrien { 227384865Sobrien return glist[i]; 227484865Sobrien } 227584865Sobrien i++; 227684865Sobrien } 227784865Sobrien } 227884865Sobrien } 227984865Sobrien for (; i > 0 && i < glistlen; i--) 228084865Sobrien { 228184865Sobrien if (ent->name->num >= glist[i - 1]->name->num) 228284865Sobrien { 228384865Sobrien break; 228484865Sobrien } 228584865Sobrien } 228684865Sobrien for (; i < glistlen; i++) 228784865Sobrien { 228884865Sobrien if (ent->name->num < glist[i]->name->num) 228984865Sobrien { 229084865Sobrien break; 229184865Sobrien } 229284865Sobrien } 229384865Sobrien for (x = glistlen - 1; x >= i; x--) 229484865Sobrien { 229584865Sobrien glist[x + 1] = glist[x]; 229684865Sobrien } 229784865Sobrien glist[i] = ent; 229884865Sobrien glistlen++; 229984865Sobrien } 230084865Sobrien return ent; 230184865Sobrien} 230284865Sobrien 230384865Sobrienstatic int 230484865Sobrienget_prefix_len (name) 230584865Sobrien const char *name; 230684865Sobrien{ 230784865Sobrien char *c; 230884865Sobrien 230984865Sobrien if (name[0] == '\0') 231084865Sobrien { 231184865Sobrien return 0; 231284865Sobrien } 231384865Sobrien 231484865Sobrien c = strchr (name, '.'); 231584865Sobrien if (c != NULL) 231684865Sobrien { 231784865Sobrien return c - name; 231884865Sobrien } 231984865Sobrien else 232084865Sobrien { 232184865Sobrien return strlen (name); 232284865Sobrien } 232384865Sobrien} 232484865Sobrien 232584865Sobrienstatic void 232684865Sobriencompute_completer_bits (ment, ent) 232784865Sobrien struct main_entry *ment; 232884865Sobrien struct completer_entry *ent; 232984865Sobrien{ 233084865Sobrien while (ent != NULL) 233184865Sobrien { 233284865Sobrien compute_completer_bits (ment, ent->addl_entries); 233384865Sobrien 233484865Sobrien if (ent->is_terminal) 233584865Sobrien { 233684865Sobrien ia64_insn mask = 0; 233784865Sobrien ia64_insn our_bits = ent->bits; 233884865Sobrien struct completer_entry *p = ent->parent; 233984865Sobrien ia64_insn p_bits; 234084865Sobrien int x; 234184865Sobrien 234284865Sobrien while (p != NULL && ! p->is_terminal) 234384865Sobrien { 234484865Sobrien p = p->parent; 234584865Sobrien } 234684865Sobrien 234784865Sobrien if (p != NULL) 234884865Sobrien { 234984865Sobrien p_bits = p->bits; 235084865Sobrien } 235184865Sobrien else 235284865Sobrien { 235384865Sobrien p_bits = ment->opcode->opcode; 235484865Sobrien } 235584865Sobrien 235684865Sobrien for (x = 0; x < 64; x++) 235784865Sobrien { 235884865Sobrien ia64_insn m = ((ia64_insn) 1) << x; 235984865Sobrien if ((p_bits & m) != (our_bits & m)) 236084865Sobrien { 236184865Sobrien mask |= m; 236284865Sobrien } 236384865Sobrien else 236484865Sobrien { 236584865Sobrien our_bits &= ~m; 236684865Sobrien } 236784865Sobrien } 236884865Sobrien ent->bits = our_bits; 236984865Sobrien ent->mask = mask; 237084865Sobrien } 237184865Sobrien else 237284865Sobrien { 237384865Sobrien ent->bits = 0; 237484865Sobrien ent->mask = 0; 237584865Sobrien } 237684865Sobrien 237784865Sobrien ent = ent->alternative; 237884865Sobrien } 237984865Sobrien} 238084865Sobrien 238184865Sobrien/* Find identical completer trees that are used in different 238284865Sobrien instructions and collapse their entries. */ 238384865Sobrienvoid 238484865Sobriencollapse_redundant_completers () 238584865Sobrien{ 238684865Sobrien struct main_entry *ptr; 238784865Sobrien int x; 238884865Sobrien 238984865Sobrien for (ptr = maintable; ptr != NULL; ptr = ptr->next) 239084865Sobrien { 239184865Sobrien if (ptr->completers == NULL) 239284865Sobrien { 239384865Sobrien abort (); 239484865Sobrien } 239584865Sobrien compute_completer_bits (ptr, ptr->completers); 239684865Sobrien ptr->completers = insert_gclist (ptr->completers); 239784865Sobrien } 239884865Sobrien 239984865Sobrien /* The table has been finalized, now number the indexes. */ 240084865Sobrien for (x = 0; x < glistlen; x++) 240184865Sobrien { 240284865Sobrien glist[x]->num = x; 240384865Sobrien } 240484865Sobrien} 240584865Sobrien 240684865Sobrien 240784865Sobrien/* attach two lists of dependencies to each opcode. 240884865Sobrien 1) all resources which, when already marked in use, conflict with this 240984865Sobrien opcode (chks) 241084865Sobrien 2) all resources which must be marked in use when this opcode is used 241184865Sobrien (regs) 241284865Sobrien*/ 241384865Sobrienint 241484865Sobrieninsert_opcode_dependencies (opc, cmp) 241584865Sobrien struct ia64_opcode *opc; 241684865Sobrien struct completer_entry *cmp ATTRIBUTE_UNUSED; 241784865Sobrien{ 241884865Sobrien /* note all resources which point to this opcode. rfi has the most chks 241984865Sobrien (79) and cmpxchng has the most regs (54) so 100 here should be enough */ 242084865Sobrien int i; 242184865Sobrien int nregs = 0; 242284865Sobrien unsigned short regs[256]; 242384865Sobrien int nchks = 0; 242484865Sobrien unsigned short chks[256]; 242584865Sobrien /* flag insns for which no class matched; there should be none */ 242684865Sobrien int no_class_found = 1; 242784865Sobrien 242884865Sobrien for (i=0;i < rdepslen;i++) 242984865Sobrien { 243084865Sobrien struct rdep *rs = rdeps[i]; 243184865Sobrien int j; 243284865Sobrien 243384865Sobrien if (strcmp (opc->name, "cmp.eq.and") == 0 243484865Sobrien && strncmp (rs->name, "PR%", 3) == 0 243584865Sobrien && rs->mode == 1) 243684865Sobrien no_class_found = 99; 243784865Sobrien 243884865Sobrien for (j=0; j < rs->nregs;j++) 243984865Sobrien { 244084865Sobrien int ic_note = 0; 244184865Sobrien 244284865Sobrien if (in_iclass (opc, ics[rs->regs[j]], NULL, NULL, &ic_note)) 244384865Sobrien { 244484865Sobrien /* We can ignore ic_note 11 for non PR resources */ 244584865Sobrien if (ic_note == 11 && strncmp (rs->name, "PR", 2) != 0) 244684865Sobrien ic_note = 0; 244784865Sobrien 244884865Sobrien if (ic_note != 0 && rs->regnotes[j] != 0 244984865Sobrien && ic_note != rs->regnotes[j] 245084865Sobrien && !(ic_note == 11 && rs->regnotes[j] == 1)) 245184865Sobrien fprintf (stderr, "Warning: IC note %d in opcode %s (IC:%s)" 245284865Sobrien " conflicts with resource %s note %d\n", 245384865Sobrien ic_note, opc->name, ics[rs->regs[j]]->name, 245484865Sobrien rs->name, rs->regnotes[j]); 245584865Sobrien /* Instruction class notes override resource notes. 245684865Sobrien So far, only note 11 applies to an IC instead of a resource, 245784865Sobrien and note 11 implies note 1. 245884865Sobrien */ 245984865Sobrien if (ic_note) 246084865Sobrien regs[nregs++] = RDEP(ic_note, i); 246184865Sobrien else 246284865Sobrien regs[nregs++] = RDEP(rs->regnotes[j], i); 246384865Sobrien no_class_found = 0; 246484865Sobrien ++rs->total_regs; 246584865Sobrien } 246684865Sobrien } 246784865Sobrien for (j=0;j < rs->nchks;j++) 246884865Sobrien { 246984865Sobrien int ic_note = 0; 247084865Sobrien 247184865Sobrien if (in_iclass (opc, ics[rs->chks[j]], NULL, NULL, &ic_note)) 247284865Sobrien { 247384865Sobrien /* We can ignore ic_note 11 for non PR resources */ 247484865Sobrien if (ic_note == 11 && strncmp (rs->name, "PR", 2) != 0) 247584865Sobrien ic_note = 0; 247684865Sobrien 247784865Sobrien if (ic_note != 0 && rs->chknotes[j] != 0 247884865Sobrien && ic_note != rs->chknotes[j] 247984865Sobrien && !(ic_note == 11 && rs->chknotes[j] == 1)) 248084865Sobrien fprintf (stderr, "Warning: IC note %d for opcode %s (IC:%s)" 248184865Sobrien " conflicts with resource %s note %d\n", 248284865Sobrien ic_note, opc->name, ics[rs->chks[j]]->name, 248384865Sobrien rs->name, rs->chknotes[j]); 248484865Sobrien if (ic_note) 248584865Sobrien chks[nchks++] = RDEP(ic_note, i); 248684865Sobrien else 248784865Sobrien chks[nchks++] = RDEP(rs->chknotes[j], i); 248884865Sobrien no_class_found = 0; 248984865Sobrien ++rs->total_chks; 249084865Sobrien } 249184865Sobrien } 249284865Sobrien } 249384865Sobrien 249484865Sobrien if (no_class_found) 249584865Sobrien fprintf (stderr, "Warning: opcode %s has no class (ops %d %d %d)\n", 249684865Sobrien opc->name, 249784865Sobrien opc->operands[0], opc->operands[1], opc->operands[2]); 249884865Sobrien 249984865Sobrien return insert_dependencies (nchks, chks, nregs, regs); 250084865Sobrien} 250184865Sobrien 250284865Sobrienvoid 250384865Sobrieninsert_completer_entry (opc, tabent, order) 250484865Sobrien struct ia64_opcode *opc; 250584865Sobrien struct main_entry *tabent; 250684865Sobrien int order; 250784865Sobrien{ 250884865Sobrien struct completer_entry **ptr = &tabent->completers; 250984865Sobrien struct completer_entry *parent = NULL; 251084865Sobrien char pcopy[129], *prefix; 251184865Sobrien int at_end = 0; 251284865Sobrien 251384865Sobrien if (strlen (opc->name) > 128) 251484865Sobrien { 251584865Sobrien abort (); 251684865Sobrien } 251784865Sobrien strcpy (pcopy, opc->name); 251884865Sobrien prefix = pcopy + get_prefix_len (pcopy); 251984865Sobrien if (prefix[0] != '\0') 252084865Sobrien { 252184865Sobrien prefix++; 252284865Sobrien } 252384865Sobrien 252484865Sobrien while (! at_end) 252584865Sobrien { 252684865Sobrien int need_new_ent = 1; 252784865Sobrien int plen = get_prefix_len (prefix); 252884865Sobrien struct string_entry *sent; 252984865Sobrien 253084865Sobrien at_end = (prefix[plen] == '\0'); 253184865Sobrien prefix[plen] = '\0'; 253284865Sobrien sent = insert_string (prefix); 253384865Sobrien 253484865Sobrien while (*ptr != NULL) 253584865Sobrien { 253684865Sobrien int cmpres = sent->num - (*ptr)->name->num; 253784865Sobrien 253884865Sobrien if (cmpres == 0) 253984865Sobrien { 254084865Sobrien need_new_ent = 0; 254184865Sobrien break; 254284865Sobrien } 254384865Sobrien else 254484865Sobrien { 254584865Sobrien ptr = &((*ptr)->alternative); 254684865Sobrien } 254784865Sobrien } 254884865Sobrien if (need_new_ent) 254984865Sobrien { 255084865Sobrien struct completer_entry *nent = tmalloc (struct completer_entry); 255184865Sobrien nent->name = sent; 255284865Sobrien nent->parent = parent; 255384865Sobrien nent->addl_entries = NULL; 255484865Sobrien nent->alternative = *ptr; 255584865Sobrien *ptr = nent; 255684865Sobrien nent->is_terminal = 0; 255784865Sobrien nent->dependencies = -1; 255884865Sobrien } 255984865Sobrien 256084865Sobrien if (! at_end) 256184865Sobrien { 256284865Sobrien parent = *ptr; 256384865Sobrien ptr = &((*ptr)->addl_entries); 256484865Sobrien prefix += plen + 1; 256584865Sobrien } 256684865Sobrien } 256784865Sobrien 256884865Sobrien if ((*ptr)->is_terminal) 256984865Sobrien { 257084865Sobrien abort (); 257184865Sobrien } 257284865Sobrien 257384865Sobrien (*ptr)->is_terminal = 1; 257484865Sobrien (*ptr)->mask = (ia64_insn)-1; 257584865Sobrien (*ptr)->bits = opc->opcode; 257684865Sobrien (*ptr)->dependencies = insert_opcode_dependencies (opc, *ptr); 257784865Sobrien (*ptr)->order = order; 257884865Sobrien} 257984865Sobrien 258084865Sobrienvoid 258184865Sobrienprint_completer_entry (ent) 258284865Sobrien struct completer_entry *ent; 258384865Sobrien{ 258484865Sobrien int moffset = 0; 258584865Sobrien ia64_insn mask = ent->mask, bits = ent->bits; 258684865Sobrien 258784865Sobrien if (mask != 0) 258884865Sobrien { 258984865Sobrien while (! (mask & 1)) 259084865Sobrien { 259184865Sobrien moffset++; 259284865Sobrien mask = mask >> 1; 259384865Sobrien bits = bits >> 1; 259484865Sobrien } 259584865Sobrien if (bits & 0xffffffff00000000LL) 259684865Sobrien { 259784865Sobrien abort (); 259884865Sobrien } 259984865Sobrien } 260084865Sobrien 260184865Sobrien printf (" { 0x%x, 0x%x, %d, %d, %d, %d, %d, %d },\n", 260284865Sobrien (int)bits, 260384865Sobrien (int)mask, 260484865Sobrien ent->name->num, 260584865Sobrien ent->alternative != NULL ? ent->alternative->num : -1, 260684865Sobrien ent->addl_entries != NULL ? ent->addl_entries->num : -1, 260784865Sobrien moffset, 260884865Sobrien ent->is_terminal ? 1 : 0, 260984865Sobrien ent->dependencies); 261084865Sobrien} 261184865Sobrien 261284865Sobrienvoid 261384865Sobrienprint_completer_table () 261484865Sobrien{ 261584865Sobrien int x; 261684865Sobrien 261784865Sobrien printf ("static const struct ia64_completer_table\ncompleter_table[] = {\n"); 261884865Sobrien for (x = 0; x < glistlen; x++) 261984865Sobrien { 262084865Sobrien print_completer_entry (glist[x]); 262184865Sobrien } 262284865Sobrien printf ("};\n\n"); 262384865Sobrien} 262484865Sobrien 262584865Sobrienint 262684865Sobrienopcodes_eq (opc1, opc2) 262784865Sobrien struct ia64_opcode *opc1; 262884865Sobrien struct ia64_opcode *opc2; 262984865Sobrien{ 263084865Sobrien int x; 263184865Sobrien int plen1, plen2; 263284865Sobrien 263384865Sobrien if ((opc1->mask != opc2->mask) || (opc1->type != opc2->type) 263484865Sobrien || (opc1->num_outputs != opc2->num_outputs) 263584865Sobrien || (opc1->flags != opc2->flags)) 263684865Sobrien { 263784865Sobrien return 0; 263884865Sobrien } 263984865Sobrien for (x = 0; x < 5; x++) 264084865Sobrien { 264184865Sobrien if (opc1->operands[x] != opc2->operands[x]) 264284865Sobrien { 264384865Sobrien return 0; 264484865Sobrien } 264584865Sobrien } 264684865Sobrien plen1 = get_prefix_len (opc1->name); 264784865Sobrien plen2 = get_prefix_len (opc2->name); 264884865Sobrien if (plen1 == plen2 && (memcmp (opc1->name, opc2->name, plen1) == 0)) 264984865Sobrien { 265084865Sobrien return 1; 265184865Sobrien } 265284865Sobrien return 0; 265384865Sobrien} 265484865Sobrien 265584865Sobrienvoid 265684865Sobrienadd_opcode_entry (opc) 265784865Sobrien struct ia64_opcode *opc; 265884865Sobrien{ 265984865Sobrien struct main_entry **place; 266084865Sobrien struct string_entry *name; 266184865Sobrien char prefix[129]; 266284865Sobrien int found_it = 0; 266384865Sobrien 266484865Sobrien if (strlen (opc->name) > 128) 266584865Sobrien { 266684865Sobrien abort (); 266784865Sobrien } 266884865Sobrien place = &maintable; 266984865Sobrien strcpy (prefix, opc->name); 267084865Sobrien prefix[get_prefix_len (prefix)] = '\0'; 267184865Sobrien name = insert_string (prefix); 267284865Sobrien 267384865Sobrien /* Walk the list of opcode table entries. If it's a new 267484865Sobrien instruction, allocate and fill in a new entry. Note 267584865Sobrien the main table is alphabetical by opcode name. */ 267684865Sobrien 267784865Sobrien while (*place != NULL) 267884865Sobrien { 267984865Sobrien if ((*place)->name->num == name->num 268084865Sobrien && opcodes_eq ((*place)->opcode, opc)) 268184865Sobrien { 268284865Sobrien found_it = 1; 268384865Sobrien break; 268484865Sobrien } 268584865Sobrien if ((*place)->name->num > name->num) 268684865Sobrien { 268784865Sobrien break; 268884865Sobrien } 268984865Sobrien place = &((*place)->next); 269084865Sobrien } 269184865Sobrien if (! found_it) 269284865Sobrien { 269384865Sobrien struct main_entry *nent = tmalloc (struct main_entry); 269484865Sobrien 269584865Sobrien nent->name = name; 269684865Sobrien nent->opcode = opc; 269784865Sobrien nent->next = *place; 269884865Sobrien nent->completers = 0; 269984865Sobrien *place = nent; 270084865Sobrien 270184865Sobrien if (otlen == ottotlen) 270284865Sobrien { 270384865Sobrien ottotlen += 20; 270484865Sobrien ordered_table = (struct main_entry **) 270584865Sobrien xrealloc (ordered_table, sizeof (struct main_entry *) * ottotlen); 270684865Sobrien } 270784865Sobrien ordered_table[otlen++] = nent; 270884865Sobrien } 270984865Sobrien 271084865Sobrien insert_completer_entry (opc, *place, opcode_count++); 271184865Sobrien} 271284865Sobrien 271384865Sobrienvoid 271484865Sobrienprint_main_table () 271584865Sobrien{ 271684865Sobrien struct main_entry *ptr = maintable; 271784865Sobrien int index = 0; 271884865Sobrien 271984865Sobrien printf ("static const struct ia64_main_table\nmain_table[] = {\n"); 272084865Sobrien while (ptr != NULL) 272184865Sobrien { 272284865Sobrien printf (" { %d, %d, %d, 0x", 272384865Sobrien ptr->name->num, 272484865Sobrien ptr->opcode->type, 272584865Sobrien ptr->opcode->num_outputs); 272684865Sobrien fprintf_vma (stdout, ptr->opcode->opcode); 272784865Sobrien printf ("ull, 0x"); 272884865Sobrien fprintf_vma (stdout, ptr->opcode->mask); 272984865Sobrien printf ("ull, { %d, %d, %d, %d, %d }, 0x%x, %d, },\n", 273084865Sobrien ptr->opcode->operands[0], 273184865Sobrien ptr->opcode->operands[1], 273284865Sobrien ptr->opcode->operands[2], 273384865Sobrien ptr->opcode->operands[3], 273484865Sobrien ptr->opcode->operands[4], 273584865Sobrien ptr->opcode->flags, 273684865Sobrien ptr->completers->num); 273784865Sobrien 273884865Sobrien ptr->main_index = index++; 273984865Sobrien 274084865Sobrien ptr = ptr->next; 274184865Sobrien } 274284865Sobrien printf ("};\n\n"); 274384865Sobrien} 274484865Sobrien 274584865Sobrienvoid 274684865Sobrienshrink (table) 274784865Sobrien struct ia64_opcode *table; 274884865Sobrien{ 274984865Sobrien int curr_opcode; 275084865Sobrien 275184865Sobrien for (curr_opcode = 0; table[curr_opcode].name != NULL; curr_opcode++) 275284865Sobrien { 275384865Sobrien add_opcode_entry (table + curr_opcode); 275484865Sobrien } 275584865Sobrien} 275684865Sobrien 275784865Sobrienint 275884865Sobrienmain (argc, argv) 275984865Sobrien int argc; 276084865Sobrien char **argv ATTRIBUTE_UNUSED; 276184865Sobrien{ 276284865Sobrien if (argc > 1) 276384865Sobrien { 276484865Sobrien debug = 1; 276584865Sobrien } 276684865Sobrien 276784865Sobrien load_insn_classes(); 276884865Sobrien load_dependencies(); 276984865Sobrien 277084865Sobrien shrink (ia64_opcodes_a); 277184865Sobrien shrink (ia64_opcodes_b); 277284865Sobrien shrink (ia64_opcodes_f); 277384865Sobrien shrink (ia64_opcodes_i); 277484865Sobrien shrink (ia64_opcodes_m); 277584865Sobrien shrink (ia64_opcodes_x); 277684865Sobrien shrink (ia64_opcodes_d); 277784865Sobrien 277884865Sobrien collapse_redundant_completers (); 277984865Sobrien 278084865Sobrien printf ("/* This file is automatically generated by ia64-gen. Do not edit! */\n"); 278184865Sobrien print_string_table (); 278284865Sobrien print_dependency_table (); 278384865Sobrien print_completer_table (); 278484865Sobrien print_main_table (); 278584865Sobrien 278684865Sobrien generate_disassembler (); 278784865Sobrien 278884865Sobrien exit (0); 278984865Sobrien} 2790