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