xref: /aosp_15_r20/external/elfutils/libcpu/i386_parse.y (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker %{
2*7304104dSAndroid Build Coastguard Worker /* Parser for i386 CPU description.
3*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2004, 2005, 2007, 2008, 2009 Red Hat, Inc.
4*7304104dSAndroid Build Coastguard Worker    Written by Ulrich Drepper <[email protected]>, 2004.
5*7304104dSAndroid Build Coastguard Worker 
6*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker    it under the terms of either
8*7304104dSAndroid Build Coastguard Worker 
9*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker        your option) any later version
12*7304104dSAndroid Build Coastguard Worker 
13*7304104dSAndroid Build Coastguard Worker    or
14*7304104dSAndroid Build Coastguard Worker 
15*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker        your option) any later version
18*7304104dSAndroid Build Coastguard Worker 
19*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker 
21*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker 
26*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
28*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
29*7304104dSAndroid Build Coastguard Worker 
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker 
34*7304104dSAndroid Build Coastguard Worker #include <assert.h>
35*7304104dSAndroid Build Coastguard Worker #include <ctype.h>
36*7304104dSAndroid Build Coastguard Worker #include <errno.h>
37*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
38*7304104dSAndroid Build Coastguard Worker #include <math.h>
39*7304104dSAndroid Build Coastguard Worker #include <obstack.h>
40*7304104dSAndroid Build Coastguard Worker #include <search.h>
41*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
42*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
43*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
44*7304104dSAndroid Build Coastguard Worker #include <string.h>
45*7304104dSAndroid Build Coastguard Worker 
46*7304104dSAndroid Build Coastguard Worker #include <libeu.h>
47*7304104dSAndroid Build Coastguard Worker #include <system.h>
48*7304104dSAndroid Build Coastguard Worker 
49*7304104dSAndroid Build Coastguard Worker #include "i386_mne.h"
50*7304104dSAndroid Build Coastguard Worker 
51*7304104dSAndroid Build Coastguard Worker #define obstack_chunk_alloc xmalloc
52*7304104dSAndroid Build Coastguard Worker #define obstack_chunk_free free
53*7304104dSAndroid Build Coastguard Worker 
54*7304104dSAndroid Build Coastguard Worker /* The error handler.  */
55*7304104dSAndroid Build Coastguard Worker static void yyerror (const char *s);
56*7304104dSAndroid Build Coastguard Worker 
57*7304104dSAndroid Build Coastguard Worker extern int yylex (void);
58*7304104dSAndroid Build Coastguard Worker extern int i386_lineno;
59*7304104dSAndroid Build Coastguard Worker extern char *infname;
60*7304104dSAndroid Build Coastguard Worker 
61*7304104dSAndroid Build Coastguard Worker 
62*7304104dSAndroid Build Coastguard Worker struct known_bitfield
63*7304104dSAndroid Build Coastguard Worker {
64*7304104dSAndroid Build Coastguard Worker   char *name;
65*7304104dSAndroid Build Coastguard Worker   unsigned long int bits;
66*7304104dSAndroid Build Coastguard Worker   int tmp;
67*7304104dSAndroid Build Coastguard Worker };
68*7304104dSAndroid Build Coastguard Worker 
69*7304104dSAndroid Build Coastguard Worker 
70*7304104dSAndroid Build Coastguard Worker struct bitvalue
71*7304104dSAndroid Build Coastguard Worker {
72*7304104dSAndroid Build Coastguard Worker   enum bittype { zeroone, field, failure } type;
73*7304104dSAndroid Build Coastguard Worker   union
74*7304104dSAndroid Build Coastguard Worker   {
75*7304104dSAndroid Build Coastguard Worker     unsigned int value;
76*7304104dSAndroid Build Coastguard Worker     struct known_bitfield *field;
77*7304104dSAndroid Build Coastguard Worker   };
78*7304104dSAndroid Build Coastguard Worker   struct bitvalue *next;
79*7304104dSAndroid Build Coastguard Worker };
80*7304104dSAndroid Build Coastguard Worker 
81*7304104dSAndroid Build Coastguard Worker 
82*7304104dSAndroid Build Coastguard Worker struct argname
83*7304104dSAndroid Build Coastguard Worker {
84*7304104dSAndroid Build Coastguard Worker   enum nametype { string, nfield } type;
85*7304104dSAndroid Build Coastguard Worker   union
86*7304104dSAndroid Build Coastguard Worker   {
87*7304104dSAndroid Build Coastguard Worker     char *str;
88*7304104dSAndroid Build Coastguard Worker     struct known_bitfield *field;
89*7304104dSAndroid Build Coastguard Worker   };
90*7304104dSAndroid Build Coastguard Worker   struct argname *next;
91*7304104dSAndroid Build Coastguard Worker };
92*7304104dSAndroid Build Coastguard Worker 
93*7304104dSAndroid Build Coastguard Worker 
94*7304104dSAndroid Build Coastguard Worker struct argument
95*7304104dSAndroid Build Coastguard Worker {
96*7304104dSAndroid Build Coastguard Worker   struct argname *name;
97*7304104dSAndroid Build Coastguard Worker   struct argument *next;
98*7304104dSAndroid Build Coastguard Worker };
99*7304104dSAndroid Build Coastguard Worker 
100*7304104dSAndroid Build Coastguard Worker 
101*7304104dSAndroid Build Coastguard Worker struct instruction
102*7304104dSAndroid Build Coastguard Worker {
103*7304104dSAndroid Build Coastguard Worker   /* The byte encoding.  */
104*7304104dSAndroid Build Coastguard Worker   struct bitvalue *bytes;
105*7304104dSAndroid Build Coastguard Worker 
106*7304104dSAndroid Build Coastguard Worker   /* Prefix possible.  */
107*7304104dSAndroid Build Coastguard Worker   int repe;
108*7304104dSAndroid Build Coastguard Worker   int rep;
109*7304104dSAndroid Build Coastguard Worker 
110*7304104dSAndroid Build Coastguard Worker   /* Mnemonic.  */
111*7304104dSAndroid Build Coastguard Worker   char *mnemonic;
112*7304104dSAndroid Build Coastguard Worker 
113*7304104dSAndroid Build Coastguard Worker   /* Suffix.  */
114*7304104dSAndroid Build Coastguard Worker   enum { suffix_none = 0, suffix_w, suffix_w0, suffix_W, suffix_tttn,
115*7304104dSAndroid Build Coastguard Worker 	 suffix_w1, suffix_W1, suffix_D } suffix;
116*7304104dSAndroid Build Coastguard Worker 
117*7304104dSAndroid Build Coastguard Worker   /* Flag set if modr/m is used.  */
118*7304104dSAndroid Build Coastguard Worker   int modrm;
119*7304104dSAndroid Build Coastguard Worker 
120*7304104dSAndroid Build Coastguard Worker   /* Operands.  */
121*7304104dSAndroid Build Coastguard Worker   struct operand
122*7304104dSAndroid Build Coastguard Worker   {
123*7304104dSAndroid Build Coastguard Worker     char *fct;
124*7304104dSAndroid Build Coastguard Worker     char *str;
125*7304104dSAndroid Build Coastguard Worker     int off1;
126*7304104dSAndroid Build Coastguard Worker     int off2;
127*7304104dSAndroid Build Coastguard Worker     int off3;
128*7304104dSAndroid Build Coastguard Worker   } operands[3];
129*7304104dSAndroid Build Coastguard Worker 
130*7304104dSAndroid Build Coastguard Worker   struct instruction *next;
131*7304104dSAndroid Build Coastguard Worker };
132*7304104dSAndroid Build Coastguard Worker 
133*7304104dSAndroid Build Coastguard Worker 
134*7304104dSAndroid Build Coastguard Worker struct synonym
135*7304104dSAndroid Build Coastguard Worker {
136*7304104dSAndroid Build Coastguard Worker   char *from;
137*7304104dSAndroid Build Coastguard Worker   char *to;
138*7304104dSAndroid Build Coastguard Worker };
139*7304104dSAndroid Build Coastguard Worker 
140*7304104dSAndroid Build Coastguard Worker 
141*7304104dSAndroid Build Coastguard Worker struct suffix
142*7304104dSAndroid Build Coastguard Worker {
143*7304104dSAndroid Build Coastguard Worker   char *name;
144*7304104dSAndroid Build Coastguard Worker   int idx;
145*7304104dSAndroid Build Coastguard Worker };
146*7304104dSAndroid Build Coastguard Worker 
147*7304104dSAndroid Build Coastguard Worker 
148*7304104dSAndroid Build Coastguard Worker struct argstring
149*7304104dSAndroid Build Coastguard Worker {
150*7304104dSAndroid Build Coastguard Worker   char *str;
151*7304104dSAndroid Build Coastguard Worker   int idx;
152*7304104dSAndroid Build Coastguard Worker   int off;
153*7304104dSAndroid Build Coastguard Worker };
154*7304104dSAndroid Build Coastguard Worker 
155*7304104dSAndroid Build Coastguard Worker 
156*7304104dSAndroid Build Coastguard Worker static struct known_bitfield ax_reg =
157*7304104dSAndroid Build Coastguard Worker   {
158*7304104dSAndroid Build Coastguard Worker     .name = "ax", .bits = 0, .tmp = 0
159*7304104dSAndroid Build Coastguard Worker   };
160*7304104dSAndroid Build Coastguard Worker 
161*7304104dSAndroid Build Coastguard Worker static struct known_bitfield dx_reg =
162*7304104dSAndroid Build Coastguard Worker   {
163*7304104dSAndroid Build Coastguard Worker     .name = "dx", .bits = 0, .tmp = 0
164*7304104dSAndroid Build Coastguard Worker   };
165*7304104dSAndroid Build Coastguard Worker 
166*7304104dSAndroid Build Coastguard Worker static struct known_bitfield di_reg =
167*7304104dSAndroid Build Coastguard Worker   {
168*7304104dSAndroid Build Coastguard Worker     .name = "es_di", .bits = 0, .tmp = 0
169*7304104dSAndroid Build Coastguard Worker   };
170*7304104dSAndroid Build Coastguard Worker 
171*7304104dSAndroid Build Coastguard Worker static struct known_bitfield si_reg =
172*7304104dSAndroid Build Coastguard Worker   {
173*7304104dSAndroid Build Coastguard Worker     .name = "ds_si", .bits = 0, .tmp = 0
174*7304104dSAndroid Build Coastguard Worker   };
175*7304104dSAndroid Build Coastguard Worker 
176*7304104dSAndroid Build Coastguard Worker static struct known_bitfield bx_reg =
177*7304104dSAndroid Build Coastguard Worker   {
178*7304104dSAndroid Build Coastguard Worker     .name = "ds_bx", .bits = 0, .tmp = 0
179*7304104dSAndroid Build Coastguard Worker   };
180*7304104dSAndroid Build Coastguard Worker 
181*7304104dSAndroid Build Coastguard Worker 
182*7304104dSAndroid Build Coastguard Worker static int bitfield_compare (const void *p1, const void *p2);
183*7304104dSAndroid Build Coastguard Worker static void new_bitfield (char *name, unsigned long int num);
184*7304104dSAndroid Build Coastguard Worker static void check_bits (struct bitvalue *value);
185*7304104dSAndroid Build Coastguard Worker static int check_duplicates (struct bitvalue *val);
186*7304104dSAndroid Build Coastguard Worker static int check_argsdef (struct bitvalue *bitval, struct argument *args);
187*7304104dSAndroid Build Coastguard Worker static int check_bitsused (struct bitvalue *bitval,
188*7304104dSAndroid Build Coastguard Worker 			   struct known_bitfield *suffix,
189*7304104dSAndroid Build Coastguard Worker 			   struct argument *args);
190*7304104dSAndroid Build Coastguard Worker static struct argname *combine (struct argname *name);
191*7304104dSAndroid Build Coastguard Worker static void fillin_arg (struct bitvalue *bytes, struct argname *name,
192*7304104dSAndroid Build Coastguard Worker 			struct instruction *instr, int n);
193*7304104dSAndroid Build Coastguard Worker static void find_numbers (void);
194*7304104dSAndroid Build Coastguard Worker static int compare_syn (const void *p1, const void *p2);
195*7304104dSAndroid Build Coastguard Worker static int compare_suf (const void *p1, const void *p2);
196*7304104dSAndroid Build Coastguard Worker static void instrtable_out (void);
197*7304104dSAndroid Build Coastguard Worker #if 0
198*7304104dSAndroid Build Coastguard Worker static void create_mnemonic_table (void);
199*7304104dSAndroid Build Coastguard Worker #endif
200*7304104dSAndroid Build Coastguard Worker 
201*7304104dSAndroid Build Coastguard Worker static void *bitfields;
202*7304104dSAndroid Build Coastguard Worker static struct instruction *instructions;
203*7304104dSAndroid Build Coastguard Worker static size_t ninstructions;
204*7304104dSAndroid Build Coastguard Worker static void *synonyms;
205*7304104dSAndroid Build Coastguard Worker static void *suffixes;
206*7304104dSAndroid Build Coastguard Worker static int nsuffixes;
207*7304104dSAndroid Build Coastguard Worker static void *mnemonics;
208*7304104dSAndroid Build Coastguard Worker size_t nmnemonics;
209*7304104dSAndroid Build Coastguard Worker extern FILE *outfile;
210*7304104dSAndroid Build Coastguard Worker 
211*7304104dSAndroid Build Coastguard Worker /* Number of bits used mnemonics.  */
212*7304104dSAndroid Build Coastguard Worker #if 0
213*7304104dSAndroid Build Coastguard Worker static size_t best_mnemonic_bits;
214*7304104dSAndroid Build Coastguard Worker #endif
215*7304104dSAndroid Build Coastguard Worker %}
216*7304104dSAndroid Build Coastguard Worker 
217*7304104dSAndroid Build Coastguard Worker %union {
218*7304104dSAndroid Build Coastguard Worker   unsigned long int num;
219*7304104dSAndroid Build Coastguard Worker   char *str;
220*7304104dSAndroid Build Coastguard Worker   char ch;
221*7304104dSAndroid Build Coastguard Worker   struct known_bitfield *field;
222*7304104dSAndroid Build Coastguard Worker   struct bitvalue *bit;
223*7304104dSAndroid Build Coastguard Worker   struct argname *name;
224*7304104dSAndroid Build Coastguard Worker   struct argument *arg;
225*7304104dSAndroid Build Coastguard Worker }
226*7304104dSAndroid Build Coastguard Worker 
227*7304104dSAndroid Build Coastguard Worker %token kMASK
228*7304104dSAndroid Build Coastguard Worker %token kPREFIX
229*7304104dSAndroid Build Coastguard Worker %token kSUFFIX
230*7304104dSAndroid Build Coastguard Worker %token kSYNONYM
231*7304104dSAndroid Build Coastguard Worker %token <str> kID
232*7304104dSAndroid Build Coastguard Worker %token <num> kNUMBER
233*7304104dSAndroid Build Coastguard Worker %token kPERCPERC
234*7304104dSAndroid Build Coastguard Worker %token <str> kBITFIELD
235*7304104dSAndroid Build Coastguard Worker %token <ch> kCHAR
236*7304104dSAndroid Build Coastguard Worker %token kSPACE
237*7304104dSAndroid Build Coastguard Worker 
238*7304104dSAndroid Build Coastguard Worker %type <bit> bit byte bytes
239*7304104dSAndroid Build Coastguard Worker %type <field> bitfieldopt
240*7304104dSAndroid Build Coastguard Worker %type <name> argcomp arg
241*7304104dSAndroid Build Coastguard Worker %type <arg> args optargs
242*7304104dSAndroid Build Coastguard Worker 
243*7304104dSAndroid Build Coastguard Worker %defines
244*7304104dSAndroid Build Coastguard Worker 
245*7304104dSAndroid Build Coastguard Worker %%
246*7304104dSAndroid Build Coastguard Worker 
247*7304104dSAndroid Build Coastguard Worker spec:		  masks kPERCPERC '\n' instrs
248*7304104dSAndroid Build Coastguard Worker 		    {
249*7304104dSAndroid Build Coastguard Worker 		      if (error_message_count != 0)
250*7304104dSAndroid Build Coastguard Worker 			error (EXIT_FAILURE, 0,
251*7304104dSAndroid Build Coastguard Worker 			       "terminated due to previous error");
252*7304104dSAndroid Build Coastguard Worker 
253*7304104dSAndroid Build Coastguard Worker 		      instrtable_out ();
254*7304104dSAndroid Build Coastguard Worker 		    }
255*7304104dSAndroid Build Coastguard Worker 		;
256*7304104dSAndroid Build Coastguard Worker 
257*7304104dSAndroid Build Coastguard Worker masks:		  masks '\n' mask
258*7304104dSAndroid Build Coastguard Worker 		| mask
259*7304104dSAndroid Build Coastguard Worker 		;
260*7304104dSAndroid Build Coastguard Worker 
261*7304104dSAndroid Build Coastguard Worker mask:		  kMASK kBITFIELD kNUMBER
262*7304104dSAndroid Build Coastguard Worker 		    { new_bitfield ($2, $3); }
263*7304104dSAndroid Build Coastguard Worker 		| kPREFIX kBITFIELD
264*7304104dSAndroid Build Coastguard Worker 		    { new_bitfield ($2, -1); }
265*7304104dSAndroid Build Coastguard Worker 		| kSUFFIX kBITFIELD
266*7304104dSAndroid Build Coastguard Worker 		    { new_bitfield ($2, -2); }
267*7304104dSAndroid Build Coastguard Worker 		| kSYNONYM kBITFIELD kBITFIELD
268*7304104dSAndroid Build Coastguard Worker 		    {
269*7304104dSAndroid Build Coastguard Worker 		      struct synonym *newp = xmalloc (sizeof (*newp));
270*7304104dSAndroid Build Coastguard Worker 		      newp->from = $2;
271*7304104dSAndroid Build Coastguard Worker 		      newp->to = $3;
272*7304104dSAndroid Build Coastguard Worker 		      if (tfind (newp, &synonyms, compare_syn) != NULL)
273*7304104dSAndroid Build Coastguard Worker 			error (0, 0,
274*7304104dSAndroid Build Coastguard Worker 			       "%d: duplicate definition for synonym '%s'",
275*7304104dSAndroid Build Coastguard Worker 			       i386_lineno, $2);
276*7304104dSAndroid Build Coastguard Worker 		      else if (tsearch ( newp, &synonyms, compare_syn) == NULL)
277*7304104dSAndroid Build Coastguard Worker 			error (EXIT_FAILURE, 0, "tsearch");
278*7304104dSAndroid Build Coastguard Worker 		    }
279*7304104dSAndroid Build Coastguard Worker 		|
280*7304104dSAndroid Build Coastguard Worker 		;
281*7304104dSAndroid Build Coastguard Worker 
282*7304104dSAndroid Build Coastguard Worker instrs:		  instrs '\n' instr
283*7304104dSAndroid Build Coastguard Worker 		| instr
284*7304104dSAndroid Build Coastguard Worker 		;
285*7304104dSAndroid Build Coastguard Worker 
286*7304104dSAndroid Build Coastguard Worker instr:		  bytes ':' bitfieldopt kID bitfieldopt optargs
287*7304104dSAndroid Build Coastguard Worker 		    {
288*7304104dSAndroid Build Coastguard Worker 		      if ($3 != NULL && strcmp ($3->name, "RE") != 0
289*7304104dSAndroid Build Coastguard Worker 			  && strcmp ($3->name, "R") != 0)
290*7304104dSAndroid Build Coastguard Worker 			{
291*7304104dSAndroid Build Coastguard Worker 			  error (0, 0, "%d: only 'R' and 'RE' prefix allowed",
292*7304104dSAndroid Build Coastguard Worker 				 i386_lineno - 1);
293*7304104dSAndroid Build Coastguard Worker 			}
294*7304104dSAndroid Build Coastguard Worker 		      if (check_duplicates ($1) == 0
295*7304104dSAndroid Build Coastguard Worker 			  && check_argsdef ($1, $6) == 0
296*7304104dSAndroid Build Coastguard Worker 			  && check_bitsused ($1, $5, $6) == 0)
297*7304104dSAndroid Build Coastguard Worker 			{
298*7304104dSAndroid Build Coastguard Worker 			  struct instruction *newp = xcalloc (sizeof (*newp),
299*7304104dSAndroid Build Coastguard Worker 							      1);
300*7304104dSAndroid Build Coastguard Worker 			  if ($3 != NULL)
301*7304104dSAndroid Build Coastguard Worker 			    {
302*7304104dSAndroid Build Coastguard Worker 			      if (strcmp ($3->name, "RE") == 0)
303*7304104dSAndroid Build Coastguard Worker 				newp->repe = 1;
304*7304104dSAndroid Build Coastguard Worker 			      else if (strcmp ($3->name, "R") == 0)
305*7304104dSAndroid Build Coastguard Worker 				newp->rep = 1;
306*7304104dSAndroid Build Coastguard Worker 			    }
307*7304104dSAndroid Build Coastguard Worker 
308*7304104dSAndroid Build Coastguard Worker 			  newp->bytes = $1;
309*7304104dSAndroid Build Coastguard Worker 			  newp->mnemonic = $4;
310*7304104dSAndroid Build Coastguard Worker 			  if (newp->mnemonic != (void *) -1l
311*7304104dSAndroid Build Coastguard Worker 			      && tfind ($4, &mnemonics,
312*7304104dSAndroid Build Coastguard Worker 					(int (*)(const void *, const void *)) strcmp) == NULL)
313*7304104dSAndroid Build Coastguard Worker 			    {
314*7304104dSAndroid Build Coastguard Worker 			      if (tsearch ($4, &mnemonics,
315*7304104dSAndroid Build Coastguard Worker 					   (int (*)(const void *, const void *)) strcmp) == NULL)
316*7304104dSAndroid Build Coastguard Worker 				error (EXIT_FAILURE, errno, "tsearch");
317*7304104dSAndroid Build Coastguard Worker 			      ++nmnemonics;
318*7304104dSAndroid Build Coastguard Worker 			    }
319*7304104dSAndroid Build Coastguard Worker 
320*7304104dSAndroid Build Coastguard Worker 			  if ($5 != NULL)
321*7304104dSAndroid Build Coastguard Worker 			    {
322*7304104dSAndroid Build Coastguard Worker 			      if (strcmp ($5->name, "w") == 0)
323*7304104dSAndroid Build Coastguard Worker 				newp->suffix = suffix_w;
324*7304104dSAndroid Build Coastguard Worker 			      else if (strcmp ($5->name, "w0") == 0)
325*7304104dSAndroid Build Coastguard Worker 				newp->suffix = suffix_w0;
326*7304104dSAndroid Build Coastguard Worker 			      else if (strcmp ($5->name, "tttn") == 0)
327*7304104dSAndroid Build Coastguard Worker 				newp->suffix = suffix_tttn;
328*7304104dSAndroid Build Coastguard Worker 			      else if (strcmp ($5->name, "w1") == 0)
329*7304104dSAndroid Build Coastguard Worker 				newp->suffix = suffix_w1;
330*7304104dSAndroid Build Coastguard Worker 			      else if (strcmp ($5->name, "W") == 0)
331*7304104dSAndroid Build Coastguard Worker 				newp->suffix = suffix_W;
332*7304104dSAndroid Build Coastguard Worker 			      else if (strcmp ($5->name, "W1") == 0)
333*7304104dSAndroid Build Coastguard Worker 				newp->suffix = suffix_W1;
334*7304104dSAndroid Build Coastguard Worker 			      else if (strcmp ($5->name, "D") == 0)
335*7304104dSAndroid Build Coastguard Worker 				newp->suffix = suffix_D;
336*7304104dSAndroid Build Coastguard Worker 			      else
337*7304104dSAndroid Build Coastguard Worker 				error (EXIT_FAILURE, 0,
338*7304104dSAndroid Build Coastguard Worker 				       "%s: %d: unknown suffix '%s'",
339*7304104dSAndroid Build Coastguard Worker 				       infname, i386_lineno - 1, $5->name);
340*7304104dSAndroid Build Coastguard Worker 
341*7304104dSAndroid Build Coastguard Worker 			      struct suffix search = { .name = $5->name };
342*7304104dSAndroid Build Coastguard Worker 			      if (tfind (&search, &suffixes, compare_suf)
343*7304104dSAndroid Build Coastguard Worker 				  == NULL)
344*7304104dSAndroid Build Coastguard Worker 				{
345*7304104dSAndroid Build Coastguard Worker 				  struct suffix *ns = xmalloc (sizeof (*ns));
346*7304104dSAndroid Build Coastguard Worker 				  ns->name = $5->name;
347*7304104dSAndroid Build Coastguard Worker 				  ns->idx = ++nsuffixes;
348*7304104dSAndroid Build Coastguard Worker 				  if (tsearch (ns, &suffixes, compare_suf)
349*7304104dSAndroid Build Coastguard Worker 				      == NULL)
350*7304104dSAndroid Build Coastguard Worker 				    error (EXIT_FAILURE, errno, "tsearch");
351*7304104dSAndroid Build Coastguard Worker 				}
352*7304104dSAndroid Build Coastguard Worker 			    }
353*7304104dSAndroid Build Coastguard Worker 
354*7304104dSAndroid Build Coastguard Worker 			  struct argument *args = $6;
355*7304104dSAndroid Build Coastguard Worker 			  int n = 0;
356*7304104dSAndroid Build Coastguard Worker 			  while (args != NULL)
357*7304104dSAndroid Build Coastguard Worker 			    {
358*7304104dSAndroid Build Coastguard Worker 			      fillin_arg ($1, args->name, newp, n);
359*7304104dSAndroid Build Coastguard Worker 
360*7304104dSAndroid Build Coastguard Worker 			      args = args->next;
361*7304104dSAndroid Build Coastguard Worker 			      ++n;
362*7304104dSAndroid Build Coastguard Worker 			    }
363*7304104dSAndroid Build Coastguard Worker 
364*7304104dSAndroid Build Coastguard Worker 			  newp->next = instructions;
365*7304104dSAndroid Build Coastguard Worker 			  instructions = newp;
366*7304104dSAndroid Build Coastguard Worker 			  ++ninstructions;
367*7304104dSAndroid Build Coastguard Worker 			}
368*7304104dSAndroid Build Coastguard Worker 		    }
369*7304104dSAndroid Build Coastguard Worker 		|
370*7304104dSAndroid Build Coastguard Worker 		;
371*7304104dSAndroid Build Coastguard Worker 
372*7304104dSAndroid Build Coastguard Worker bitfieldopt:	  kBITFIELD
373*7304104dSAndroid Build Coastguard Worker 		    {
374*7304104dSAndroid Build Coastguard Worker 		      struct known_bitfield search;
375*7304104dSAndroid Build Coastguard Worker 		      search.name = $1;
376*7304104dSAndroid Build Coastguard Worker 		      struct known_bitfield **res;
377*7304104dSAndroid Build Coastguard Worker 		      res = tfind (&search, &bitfields, bitfield_compare);
378*7304104dSAndroid Build Coastguard Worker 		      if (res == NULL)
379*7304104dSAndroid Build Coastguard Worker 			{
380*7304104dSAndroid Build Coastguard Worker 			  error (0, 0, "%d: unknown bitfield '%s'",
381*7304104dSAndroid Build Coastguard Worker 				 i386_lineno, search.name);
382*7304104dSAndroid Build Coastguard Worker 			  $$ = NULL;
383*7304104dSAndroid Build Coastguard Worker 			}
384*7304104dSAndroid Build Coastguard Worker 		      else
385*7304104dSAndroid Build Coastguard Worker 			$$ = *res;
386*7304104dSAndroid Build Coastguard Worker 		    }
387*7304104dSAndroid Build Coastguard Worker 		|
388*7304104dSAndroid Build Coastguard Worker 		    { $$ = NULL; }
389*7304104dSAndroid Build Coastguard Worker 		;
390*7304104dSAndroid Build Coastguard Worker 
391*7304104dSAndroid Build Coastguard Worker bytes:		  bytes ',' byte
392*7304104dSAndroid Build Coastguard Worker 		    {
393*7304104dSAndroid Build Coastguard Worker 		      check_bits ($3);
394*7304104dSAndroid Build Coastguard Worker 
395*7304104dSAndroid Build Coastguard Worker 		      struct bitvalue *runp = $1;
396*7304104dSAndroid Build Coastguard Worker 		      while (runp->next != NULL)
397*7304104dSAndroid Build Coastguard Worker 			runp = runp->next;
398*7304104dSAndroid Build Coastguard Worker 		      runp->next = $3;
399*7304104dSAndroid Build Coastguard Worker 		      $$ = $1;
400*7304104dSAndroid Build Coastguard Worker 		    }
401*7304104dSAndroid Build Coastguard Worker 		| byte
402*7304104dSAndroid Build Coastguard Worker 		    {
403*7304104dSAndroid Build Coastguard Worker 		      check_bits ($1);
404*7304104dSAndroid Build Coastguard Worker 		      $$ = $1;
405*7304104dSAndroid Build Coastguard Worker 		    }
406*7304104dSAndroid Build Coastguard Worker 		;
407*7304104dSAndroid Build Coastguard Worker 
408*7304104dSAndroid Build Coastguard Worker byte:		  byte bit
409*7304104dSAndroid Build Coastguard Worker 		    {
410*7304104dSAndroid Build Coastguard Worker 		      struct bitvalue *runp = $1;
411*7304104dSAndroid Build Coastguard Worker 		      while (runp->next != NULL)
412*7304104dSAndroid Build Coastguard Worker 			runp = runp->next;
413*7304104dSAndroid Build Coastguard Worker 		      runp->next = $2;
414*7304104dSAndroid Build Coastguard Worker 		      $$ = $1;
415*7304104dSAndroid Build Coastguard Worker 		    }
416*7304104dSAndroid Build Coastguard Worker 		| bit
417*7304104dSAndroid Build Coastguard Worker 		    { $$ = $1; }
418*7304104dSAndroid Build Coastguard Worker 		;
419*7304104dSAndroid Build Coastguard Worker 
420*7304104dSAndroid Build Coastguard Worker bit:		  '0'
421*7304104dSAndroid Build Coastguard Worker 		    {
422*7304104dSAndroid Build Coastguard Worker 		      $$ = xmalloc (sizeof (struct bitvalue));
423*7304104dSAndroid Build Coastguard Worker 		      $$->type = zeroone;
424*7304104dSAndroid Build Coastguard Worker 		      $$->value = 0;
425*7304104dSAndroid Build Coastguard Worker 		      $$->next = NULL;
426*7304104dSAndroid Build Coastguard Worker 		    }
427*7304104dSAndroid Build Coastguard Worker 		| '1'
428*7304104dSAndroid Build Coastguard Worker 		    {
429*7304104dSAndroid Build Coastguard Worker 		      $$ = xmalloc (sizeof (struct bitvalue));
430*7304104dSAndroid Build Coastguard Worker 		      $$->type = zeroone;
431*7304104dSAndroid Build Coastguard Worker 		      $$->value = 1;
432*7304104dSAndroid Build Coastguard Worker 		      $$->next = NULL;
433*7304104dSAndroid Build Coastguard Worker 		    }
434*7304104dSAndroid Build Coastguard Worker 		| kBITFIELD
435*7304104dSAndroid Build Coastguard Worker 		    {
436*7304104dSAndroid Build Coastguard Worker 		      $$ = xmalloc (sizeof (struct bitvalue));
437*7304104dSAndroid Build Coastguard Worker 		      struct known_bitfield search;
438*7304104dSAndroid Build Coastguard Worker 		      search.name = $1;
439*7304104dSAndroid Build Coastguard Worker 		      struct known_bitfield **res;
440*7304104dSAndroid Build Coastguard Worker 		      res = tfind (&search, &bitfields, bitfield_compare);
441*7304104dSAndroid Build Coastguard Worker 		      if (res == NULL)
442*7304104dSAndroid Build Coastguard Worker 			{
443*7304104dSAndroid Build Coastguard Worker 			  error (0, 0, "%d: unknown bitfield '%s'",
444*7304104dSAndroid Build Coastguard Worker 				 i386_lineno, search.name);
445*7304104dSAndroid Build Coastguard Worker 			  $$->type = failure;
446*7304104dSAndroid Build Coastguard Worker 			}
447*7304104dSAndroid Build Coastguard Worker 		      else
448*7304104dSAndroid Build Coastguard Worker 			{
449*7304104dSAndroid Build Coastguard Worker 			  $$->type = field;
450*7304104dSAndroid Build Coastguard Worker 			  $$->field = *res;
451*7304104dSAndroid Build Coastguard Worker 			}
452*7304104dSAndroid Build Coastguard Worker 		      $$->next = NULL;
453*7304104dSAndroid Build Coastguard Worker 		    }
454*7304104dSAndroid Build Coastguard Worker 		;
455*7304104dSAndroid Build Coastguard Worker 
456*7304104dSAndroid Build Coastguard Worker optargs:	  kSPACE args
457*7304104dSAndroid Build Coastguard Worker 		    { $$ = $2; }
458*7304104dSAndroid Build Coastguard Worker 		|
459*7304104dSAndroid Build Coastguard Worker 		    { $$ = NULL; }
460*7304104dSAndroid Build Coastguard Worker 		;
461*7304104dSAndroid Build Coastguard Worker 
462*7304104dSAndroid Build Coastguard Worker args:		  args ',' arg
463*7304104dSAndroid Build Coastguard Worker 		    {
464*7304104dSAndroid Build Coastguard Worker 		      struct argument *runp = $1;
465*7304104dSAndroid Build Coastguard Worker 		      while (runp->next != NULL)
466*7304104dSAndroid Build Coastguard Worker 			runp = runp->next;
467*7304104dSAndroid Build Coastguard Worker 		      runp->next = xmalloc (sizeof (struct argument));
468*7304104dSAndroid Build Coastguard Worker 		      runp->next->name = combine ($3);
469*7304104dSAndroid Build Coastguard Worker 		      runp->next->next = NULL;
470*7304104dSAndroid Build Coastguard Worker 		      $$ = $1;
471*7304104dSAndroid Build Coastguard Worker 		    }
472*7304104dSAndroid Build Coastguard Worker 		| arg
473*7304104dSAndroid Build Coastguard Worker 		    {
474*7304104dSAndroid Build Coastguard Worker 		      $$ = xmalloc (sizeof (struct argument));
475*7304104dSAndroid Build Coastguard Worker 		      $$->name = combine ($1);
476*7304104dSAndroid Build Coastguard Worker 		      $$->next = NULL;
477*7304104dSAndroid Build Coastguard Worker 		    }
478*7304104dSAndroid Build Coastguard Worker 		;
479*7304104dSAndroid Build Coastguard Worker 
480*7304104dSAndroid Build Coastguard Worker arg:		  arg argcomp
481*7304104dSAndroid Build Coastguard Worker 		    {
482*7304104dSAndroid Build Coastguard Worker 		      struct argname *runp = $1;
483*7304104dSAndroid Build Coastguard Worker 		      while (runp->next != NULL)
484*7304104dSAndroid Build Coastguard Worker 			runp = runp->next;
485*7304104dSAndroid Build Coastguard Worker 		      runp->next = $2;
486*7304104dSAndroid Build Coastguard Worker 		      $$ = $1;
487*7304104dSAndroid Build Coastguard Worker 		    }
488*7304104dSAndroid Build Coastguard Worker 		| argcomp
489*7304104dSAndroid Build Coastguard Worker 		    { $$ = $1; }
490*7304104dSAndroid Build Coastguard Worker 		;
491*7304104dSAndroid Build Coastguard Worker argcomp:	  kBITFIELD
492*7304104dSAndroid Build Coastguard Worker 		    {
493*7304104dSAndroid Build Coastguard Worker 		      $$ = xmalloc (sizeof (struct argname));
494*7304104dSAndroid Build Coastguard Worker 		      $$->type = nfield;
495*7304104dSAndroid Build Coastguard Worker 		      $$->next = NULL;
496*7304104dSAndroid Build Coastguard Worker 
497*7304104dSAndroid Build Coastguard Worker 		      struct known_bitfield search;
498*7304104dSAndroid Build Coastguard Worker 		      search.name = $1;
499*7304104dSAndroid Build Coastguard Worker 		      struct known_bitfield **res;
500*7304104dSAndroid Build Coastguard Worker 		      res = tfind (&search, &bitfields, bitfield_compare);
501*7304104dSAndroid Build Coastguard Worker 		      if (res == NULL)
502*7304104dSAndroid Build Coastguard Worker 			{
503*7304104dSAndroid Build Coastguard Worker 			  if (strcmp ($1, "ax") == 0)
504*7304104dSAndroid Build Coastguard Worker 			    $$->field = &ax_reg;
505*7304104dSAndroid Build Coastguard Worker 			  else if (strcmp ($1, "dx") == 0)
506*7304104dSAndroid Build Coastguard Worker 			    $$->field = &dx_reg;
507*7304104dSAndroid Build Coastguard Worker 			  else if (strcmp ($1, "es_di") == 0)
508*7304104dSAndroid Build Coastguard Worker 			    $$->field = &di_reg;
509*7304104dSAndroid Build Coastguard Worker 			  else if (strcmp ($1, "ds_si") == 0)
510*7304104dSAndroid Build Coastguard Worker 			    $$->field = &si_reg;
511*7304104dSAndroid Build Coastguard Worker 			  else if (strcmp ($1, "ds_bx") == 0)
512*7304104dSAndroid Build Coastguard Worker 			    $$->field = &bx_reg;
513*7304104dSAndroid Build Coastguard Worker 			  else
514*7304104dSAndroid Build Coastguard Worker 			    {
515*7304104dSAndroid Build Coastguard Worker 			      error (0, 0, "%d: unknown bitfield '%s'",
516*7304104dSAndroid Build Coastguard Worker 				     i386_lineno, search.name);
517*7304104dSAndroid Build Coastguard Worker 			      $$->field = NULL;
518*7304104dSAndroid Build Coastguard Worker 			    }
519*7304104dSAndroid Build Coastguard Worker 			}
520*7304104dSAndroid Build Coastguard Worker 		      else
521*7304104dSAndroid Build Coastguard Worker 			$$->field = *res;
522*7304104dSAndroid Build Coastguard Worker 		    }
523*7304104dSAndroid Build Coastguard Worker 		| kCHAR
524*7304104dSAndroid Build Coastguard Worker 		    {
525*7304104dSAndroid Build Coastguard Worker 		      $$ = xmalloc (sizeof (struct argname));
526*7304104dSAndroid Build Coastguard Worker 		      $$->type = string;
527*7304104dSAndroid Build Coastguard Worker 		      $$->next = NULL;
528*7304104dSAndroid Build Coastguard Worker 		      $$->str = xmalloc (2);
529*7304104dSAndroid Build Coastguard Worker 		      $$->str[0] = $1;
530*7304104dSAndroid Build Coastguard Worker 		      $$->str[1] = '\0';
531*7304104dSAndroid Build Coastguard Worker 		    }
532*7304104dSAndroid Build Coastguard Worker 		| kID
533*7304104dSAndroid Build Coastguard Worker 		    {
534*7304104dSAndroid Build Coastguard Worker 		      $$ = xmalloc (sizeof (struct argname));
535*7304104dSAndroid Build Coastguard Worker 		      $$->type = string;
536*7304104dSAndroid Build Coastguard Worker 		      $$->next = NULL;
537*7304104dSAndroid Build Coastguard Worker 		      $$->str = $1;
538*7304104dSAndroid Build Coastguard Worker 		    }
539*7304104dSAndroid Build Coastguard Worker 		| ':'
540*7304104dSAndroid Build Coastguard Worker 		    {
541*7304104dSAndroid Build Coastguard Worker 		      $$ = xmalloc (sizeof (struct argname));
542*7304104dSAndroid Build Coastguard Worker 		      $$->type = string;
543*7304104dSAndroid Build Coastguard Worker 		      $$->next = NULL;
544*7304104dSAndroid Build Coastguard Worker 		      $$->str = xmalloc (2);
545*7304104dSAndroid Build Coastguard Worker 		      $$->str[0] = ':';
546*7304104dSAndroid Build Coastguard Worker 		      $$->str[1] = '\0';
547*7304104dSAndroid Build Coastguard Worker 		    }
548*7304104dSAndroid Build Coastguard Worker 		;
549*7304104dSAndroid Build Coastguard Worker 
550*7304104dSAndroid Build Coastguard Worker %%
551*7304104dSAndroid Build Coastguard Worker 
552*7304104dSAndroid Build Coastguard Worker static void
553*7304104dSAndroid Build Coastguard Worker yyerror (const char *s)
554*7304104dSAndroid Build Coastguard Worker {
555*7304104dSAndroid Build Coastguard Worker   error (0, 0, _("while reading i386 CPU description: %s at line %d"),
556*7304104dSAndroid Build Coastguard Worker          _(s), i386_lineno);
557*7304104dSAndroid Build Coastguard Worker }
558*7304104dSAndroid Build Coastguard Worker 
559*7304104dSAndroid Build Coastguard Worker 
560*7304104dSAndroid Build Coastguard Worker static int
bitfield_compare(const void * p1,const void * p2)561*7304104dSAndroid Build Coastguard Worker bitfield_compare (const void *p1, const void *p2)
562*7304104dSAndroid Build Coastguard Worker {
563*7304104dSAndroid Build Coastguard Worker   struct known_bitfield *f1 = (struct known_bitfield *) p1;
564*7304104dSAndroid Build Coastguard Worker   struct known_bitfield *f2 = (struct known_bitfield *) p2;
565*7304104dSAndroid Build Coastguard Worker 
566*7304104dSAndroid Build Coastguard Worker   return strcmp (f1->name, f2->name);
567*7304104dSAndroid Build Coastguard Worker }
568*7304104dSAndroid Build Coastguard Worker 
569*7304104dSAndroid Build Coastguard Worker 
570*7304104dSAndroid Build Coastguard Worker static void
new_bitfield(char * name,unsigned long int num)571*7304104dSAndroid Build Coastguard Worker new_bitfield (char *name, unsigned long int num)
572*7304104dSAndroid Build Coastguard Worker {
573*7304104dSAndroid Build Coastguard Worker   struct known_bitfield *newp = xmalloc (sizeof (struct known_bitfield));
574*7304104dSAndroid Build Coastguard Worker   newp->name = name;
575*7304104dSAndroid Build Coastguard Worker   newp->bits = num;
576*7304104dSAndroid Build Coastguard Worker   newp->tmp = 0;
577*7304104dSAndroid Build Coastguard Worker 
578*7304104dSAndroid Build Coastguard Worker   if (tfind (newp, &bitfields, bitfield_compare) != NULL)
579*7304104dSAndroid Build Coastguard Worker     {
580*7304104dSAndroid Build Coastguard Worker       error (0, 0, "%d: duplicated definition of bitfield '%s'",
581*7304104dSAndroid Build Coastguard Worker 	     i386_lineno, name);
582*7304104dSAndroid Build Coastguard Worker       free (name);
583*7304104dSAndroid Build Coastguard Worker       free (newp);
584*7304104dSAndroid Build Coastguard Worker       return;
585*7304104dSAndroid Build Coastguard Worker     }
586*7304104dSAndroid Build Coastguard Worker 
587*7304104dSAndroid Build Coastguard Worker   if (tsearch (newp, &bitfields, bitfield_compare) == NULL)
588*7304104dSAndroid Build Coastguard Worker     error (EXIT_FAILURE, errno, "%d: cannot insert new bitfield '%s'",
589*7304104dSAndroid Build Coastguard Worker 	   i386_lineno, name);
590*7304104dSAndroid Build Coastguard Worker }
591*7304104dSAndroid Build Coastguard Worker 
592*7304104dSAndroid Build Coastguard Worker 
593*7304104dSAndroid Build Coastguard Worker /* Check that the number of bits is a multiple of 8.  */
594*7304104dSAndroid Build Coastguard Worker static void
check_bits(struct bitvalue * val)595*7304104dSAndroid Build Coastguard Worker check_bits (struct bitvalue *val)
596*7304104dSAndroid Build Coastguard Worker {
597*7304104dSAndroid Build Coastguard Worker   struct bitvalue *runp = val;
598*7304104dSAndroid Build Coastguard Worker   unsigned int total = 0;
599*7304104dSAndroid Build Coastguard Worker 
600*7304104dSAndroid Build Coastguard Worker   while (runp != NULL)
601*7304104dSAndroid Build Coastguard Worker     {
602*7304104dSAndroid Build Coastguard Worker       if (runp->type == zeroone)
603*7304104dSAndroid Build Coastguard Worker 	++total;
604*7304104dSAndroid Build Coastguard Worker       else if (runp->field == NULL)
605*7304104dSAndroid Build Coastguard Worker 	/* No sense doing anything, the field is not known.  */
606*7304104dSAndroid Build Coastguard Worker 	return;
607*7304104dSAndroid Build Coastguard Worker       else
608*7304104dSAndroid Build Coastguard Worker 	total += runp->field->bits;
609*7304104dSAndroid Build Coastguard Worker 
610*7304104dSAndroid Build Coastguard Worker       runp = runp->next;
611*7304104dSAndroid Build Coastguard Worker     }
612*7304104dSAndroid Build Coastguard Worker 
613*7304104dSAndroid Build Coastguard Worker   if (total % 8 != 0)
614*7304104dSAndroid Build Coastguard Worker     {
615*7304104dSAndroid Build Coastguard Worker       struct obstack os;
616*7304104dSAndroid Build Coastguard Worker       obstack_init (&os);
617*7304104dSAndroid Build Coastguard Worker 
618*7304104dSAndroid Build Coastguard Worker       while (val != NULL)
619*7304104dSAndroid Build Coastguard Worker 	{
620*7304104dSAndroid Build Coastguard Worker 	  if (val->type == zeroone)
621*7304104dSAndroid Build Coastguard Worker 	    obstack_printf (&os, "%u", val->value);
622*7304104dSAndroid Build Coastguard Worker 	  else
623*7304104dSAndroid Build Coastguard Worker 	    obstack_printf (&os, "{%s}", val->field->name);
624*7304104dSAndroid Build Coastguard Worker 	  val = val->next;
625*7304104dSAndroid Build Coastguard Worker 	}
626*7304104dSAndroid Build Coastguard Worker       obstack_1grow (&os, '\0');
627*7304104dSAndroid Build Coastguard Worker 
628*7304104dSAndroid Build Coastguard Worker       error (0, 0, "%d: field '%s' not a multiple of 8 bits in size",
629*7304104dSAndroid Build Coastguard Worker 	     i386_lineno, (char *) obstack_finish (&os));
630*7304104dSAndroid Build Coastguard Worker 
631*7304104dSAndroid Build Coastguard Worker       obstack_free (&os, NULL);
632*7304104dSAndroid Build Coastguard Worker     }
633*7304104dSAndroid Build Coastguard Worker }
634*7304104dSAndroid Build Coastguard Worker 
635*7304104dSAndroid Build Coastguard Worker 
636*7304104dSAndroid Build Coastguard Worker static int
check_duplicates(struct bitvalue * val)637*7304104dSAndroid Build Coastguard Worker check_duplicates (struct bitvalue *val)
638*7304104dSAndroid Build Coastguard Worker {
639*7304104dSAndroid Build Coastguard Worker   static int testcnt;
640*7304104dSAndroid Build Coastguard Worker   ++testcnt;
641*7304104dSAndroid Build Coastguard Worker 
642*7304104dSAndroid Build Coastguard Worker   int result = 0;
643*7304104dSAndroid Build Coastguard Worker   while (val != NULL)
644*7304104dSAndroid Build Coastguard Worker     {
645*7304104dSAndroid Build Coastguard Worker       if (val->type == field && val->field != NULL)
646*7304104dSAndroid Build Coastguard Worker 	{
647*7304104dSAndroid Build Coastguard Worker 	  if (val->field->tmp == testcnt)
648*7304104dSAndroid Build Coastguard Worker 	    {
649*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, "%d: bitfield '%s' used more than once",
650*7304104dSAndroid Build Coastguard Worker 		     i386_lineno - 1, val->field->name);
651*7304104dSAndroid Build Coastguard Worker 	      result = 1;
652*7304104dSAndroid Build Coastguard Worker 	    }
653*7304104dSAndroid Build Coastguard Worker 	  val->field->tmp = testcnt;
654*7304104dSAndroid Build Coastguard Worker 	}
655*7304104dSAndroid Build Coastguard Worker 
656*7304104dSAndroid Build Coastguard Worker       val = val->next;
657*7304104dSAndroid Build Coastguard Worker     }
658*7304104dSAndroid Build Coastguard Worker 
659*7304104dSAndroid Build Coastguard Worker   return result;
660*7304104dSAndroid Build Coastguard Worker }
661*7304104dSAndroid Build Coastguard Worker 
662*7304104dSAndroid Build Coastguard Worker 
663*7304104dSAndroid Build Coastguard Worker static int
check_argsdef(struct bitvalue * bitval,struct argument * args)664*7304104dSAndroid Build Coastguard Worker check_argsdef (struct bitvalue *bitval, struct argument *args)
665*7304104dSAndroid Build Coastguard Worker {
666*7304104dSAndroid Build Coastguard Worker   int result = 0;
667*7304104dSAndroid Build Coastguard Worker 
668*7304104dSAndroid Build Coastguard Worker   while (args != NULL)
669*7304104dSAndroid Build Coastguard Worker     {
670*7304104dSAndroid Build Coastguard Worker       for (struct argname *name = args->name; name != NULL; name = name->next)
671*7304104dSAndroid Build Coastguard Worker 	if (name->type == nfield && name->field != NULL
672*7304104dSAndroid Build Coastguard Worker 	    && name->field != &ax_reg && name->field != &dx_reg
673*7304104dSAndroid Build Coastguard Worker 	    && name->field != &di_reg && name->field != &si_reg
674*7304104dSAndroid Build Coastguard Worker 	    && name->field != &bx_reg)
675*7304104dSAndroid Build Coastguard Worker 	  {
676*7304104dSAndroid Build Coastguard Worker 	    struct bitvalue *runp = bitval;
677*7304104dSAndroid Build Coastguard Worker 
678*7304104dSAndroid Build Coastguard Worker 	    while (runp != NULL)
679*7304104dSAndroid Build Coastguard Worker 	      if (runp->type == field && runp->field == name->field)
680*7304104dSAndroid Build Coastguard Worker 		break;
681*7304104dSAndroid Build Coastguard Worker 	      else
682*7304104dSAndroid Build Coastguard Worker 		runp = runp->next;
683*7304104dSAndroid Build Coastguard Worker 
684*7304104dSAndroid Build Coastguard Worker 	    if (runp == NULL)
685*7304104dSAndroid Build Coastguard Worker 	      {
686*7304104dSAndroid Build Coastguard Worker 		error (0, 0, "%d: unknown bitfield '%s' used in output format",
687*7304104dSAndroid Build Coastguard Worker 		       i386_lineno - 1, name->field->name);
688*7304104dSAndroid Build Coastguard Worker 		result = 1;
689*7304104dSAndroid Build Coastguard Worker 	      }
690*7304104dSAndroid Build Coastguard Worker 	  }
691*7304104dSAndroid Build Coastguard Worker 
692*7304104dSAndroid Build Coastguard Worker       args = args->next;
693*7304104dSAndroid Build Coastguard Worker     }
694*7304104dSAndroid Build Coastguard Worker 
695*7304104dSAndroid Build Coastguard Worker   return result;
696*7304104dSAndroid Build Coastguard Worker }
697*7304104dSAndroid Build Coastguard Worker 
698*7304104dSAndroid Build Coastguard Worker 
699*7304104dSAndroid Build Coastguard Worker static int
check_bitsused(struct bitvalue * bitval,struct known_bitfield * suffix,struct argument * args)700*7304104dSAndroid Build Coastguard Worker check_bitsused (struct bitvalue *bitval, struct known_bitfield *suffix,
701*7304104dSAndroid Build Coastguard Worker 		struct argument *args)
702*7304104dSAndroid Build Coastguard Worker {
703*7304104dSAndroid Build Coastguard Worker   int result = 0;
704*7304104dSAndroid Build Coastguard Worker 
705*7304104dSAndroid Build Coastguard Worker   while (bitval != NULL)
706*7304104dSAndroid Build Coastguard Worker     {
707*7304104dSAndroid Build Coastguard Worker       if (bitval->type == field && bitval->field != NULL
708*7304104dSAndroid Build Coastguard Worker 	  && bitval->field != suffix
709*7304104dSAndroid Build Coastguard Worker 	  /* {w} is handled special.  */
710*7304104dSAndroid Build Coastguard Worker 	  && strcmp (bitval->field->name, "w") != 0)
711*7304104dSAndroid Build Coastguard Worker 	{
712*7304104dSAndroid Build Coastguard Worker 	  struct argument *runp;
713*7304104dSAndroid Build Coastguard Worker 	  for (runp = args; runp != NULL; runp = runp->next)
714*7304104dSAndroid Build Coastguard Worker 	    {
715*7304104dSAndroid Build Coastguard Worker 	      struct argname *name = runp->name;
716*7304104dSAndroid Build Coastguard Worker 
717*7304104dSAndroid Build Coastguard Worker 	      while (name != NULL)
718*7304104dSAndroid Build Coastguard Worker 		if (name->type == nfield && name->field == bitval->field)
719*7304104dSAndroid Build Coastguard Worker 		  break;
720*7304104dSAndroid Build Coastguard Worker 		else
721*7304104dSAndroid Build Coastguard Worker 		  name = name->next;
722*7304104dSAndroid Build Coastguard Worker 
723*7304104dSAndroid Build Coastguard Worker 	      if (name != NULL)
724*7304104dSAndroid Build Coastguard Worker 		break;
725*7304104dSAndroid Build Coastguard Worker 	    }
726*7304104dSAndroid Build Coastguard Worker 
727*7304104dSAndroid Build Coastguard Worker #if 0
728*7304104dSAndroid Build Coastguard Worker 	  if (runp == NULL)
729*7304104dSAndroid Build Coastguard Worker 	    {
730*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, "%d: bitfield '%s' not used",
731*7304104dSAndroid Build Coastguard Worker 		     i386_lineno - 1, bitval->field->name);
732*7304104dSAndroid Build Coastguard Worker 	      result = 1;
733*7304104dSAndroid Build Coastguard Worker 	    }
734*7304104dSAndroid Build Coastguard Worker #endif
735*7304104dSAndroid Build Coastguard Worker 	}
736*7304104dSAndroid Build Coastguard Worker 
737*7304104dSAndroid Build Coastguard Worker       bitval = bitval->next;
738*7304104dSAndroid Build Coastguard Worker     }
739*7304104dSAndroid Build Coastguard Worker 
740*7304104dSAndroid Build Coastguard Worker   return result;
741*7304104dSAndroid Build Coastguard Worker }
742*7304104dSAndroid Build Coastguard Worker 
743*7304104dSAndroid Build Coastguard Worker 
744*7304104dSAndroid Build Coastguard Worker static struct argname *
combine(struct argname * name)745*7304104dSAndroid Build Coastguard Worker combine (struct argname *name)
746*7304104dSAndroid Build Coastguard Worker {
747*7304104dSAndroid Build Coastguard Worker   struct argname *last_str = NULL;
748*7304104dSAndroid Build Coastguard Worker   for (struct argname *runp = name; runp != NULL; runp = runp->next)
749*7304104dSAndroid Build Coastguard Worker     {
750*7304104dSAndroid Build Coastguard Worker       if (runp->type == string)
751*7304104dSAndroid Build Coastguard Worker 	{
752*7304104dSAndroid Build Coastguard Worker 	  if (last_str == NULL)
753*7304104dSAndroid Build Coastguard Worker 	    last_str = runp;
754*7304104dSAndroid Build Coastguard Worker 	  else
755*7304104dSAndroid Build Coastguard Worker 	    {
756*7304104dSAndroid Build Coastguard Worker 	      last_str->str = xrealloc (last_str->str,
757*7304104dSAndroid Build Coastguard Worker 					strlen (last_str->str)
758*7304104dSAndroid Build Coastguard Worker 					+ strlen (runp->str) + 1);
759*7304104dSAndroid Build Coastguard Worker 	      strcat (last_str->str, runp->str);
760*7304104dSAndroid Build Coastguard Worker 	      last_str->next = runp->next;
761*7304104dSAndroid Build Coastguard Worker 	    }
762*7304104dSAndroid Build Coastguard Worker 	}
763*7304104dSAndroid Build Coastguard Worker       else
764*7304104dSAndroid Build Coastguard Worker 	last_str = NULL;
765*7304104dSAndroid Build Coastguard Worker     }
766*7304104dSAndroid Build Coastguard Worker   return name;
767*7304104dSAndroid Build Coastguard Worker }
768*7304104dSAndroid Build Coastguard Worker 
769*7304104dSAndroid Build Coastguard Worker 
770*7304104dSAndroid Build Coastguard Worker #define obstack_grow_str(ob, str) obstack_grow (ob, str, strlen (str))
771*7304104dSAndroid Build Coastguard Worker 
772*7304104dSAndroid Build Coastguard Worker 
773*7304104dSAndroid Build Coastguard Worker static void
fillin_arg(struct bitvalue * bytes,struct argname * name,struct instruction * instr,int n)774*7304104dSAndroid Build Coastguard Worker fillin_arg (struct bitvalue *bytes, struct argname *name,
775*7304104dSAndroid Build Coastguard Worker 	    struct instruction *instr, int n)
776*7304104dSAndroid Build Coastguard Worker {
777*7304104dSAndroid Build Coastguard Worker   static struct obstack ob;
778*7304104dSAndroid Build Coastguard Worker   static int initialized;
779*7304104dSAndroid Build Coastguard Worker   if (! initialized)
780*7304104dSAndroid Build Coastguard Worker     {
781*7304104dSAndroid Build Coastguard Worker       initialized = 1;
782*7304104dSAndroid Build Coastguard Worker       obstack_init (&ob);
783*7304104dSAndroid Build Coastguard Worker     }
784*7304104dSAndroid Build Coastguard Worker 
785*7304104dSAndroid Build Coastguard Worker   struct argname *runp = name;
786*7304104dSAndroid Build Coastguard Worker   int cnt = 0;
787*7304104dSAndroid Build Coastguard Worker   while (runp != NULL)
788*7304104dSAndroid Build Coastguard Worker     {
789*7304104dSAndroid Build Coastguard Worker       /* We ignore strings in the function name.  */
790*7304104dSAndroid Build Coastguard Worker       if (runp->type == string)
791*7304104dSAndroid Build Coastguard Worker 	{
792*7304104dSAndroid Build Coastguard Worker 	  if (instr->operands[n].str != NULL)
793*7304104dSAndroid Build Coastguard Worker 	    error (EXIT_FAILURE, 0,
794*7304104dSAndroid Build Coastguard Worker 		   "%d: cannot have more than one string parameter",
795*7304104dSAndroid Build Coastguard Worker 		   i386_lineno - 1);
796*7304104dSAndroid Build Coastguard Worker 
797*7304104dSAndroid Build Coastguard Worker 	  instr->operands[n].str = runp->str;
798*7304104dSAndroid Build Coastguard Worker 	}
799*7304104dSAndroid Build Coastguard Worker       else
800*7304104dSAndroid Build Coastguard Worker 	{
801*7304104dSAndroid Build Coastguard Worker 	  assert (runp->type == nfield);
802*7304104dSAndroid Build Coastguard Worker 
803*7304104dSAndroid Build Coastguard Worker 	  /* Construct the function name.  */
804*7304104dSAndroid Build Coastguard Worker 	  if (cnt++ > 0)
805*7304104dSAndroid Build Coastguard Worker 	    obstack_1grow (&ob, '$');
806*7304104dSAndroid Build Coastguard Worker 
807*7304104dSAndroid Build Coastguard Worker 	  if (runp->field == NULL)
808*7304104dSAndroid Build Coastguard Worker 	    /* Add some string which contains invalid characters.  */
809*7304104dSAndroid Build Coastguard Worker 	    obstack_grow_str (&ob, "!!!INVALID!!!");
810*7304104dSAndroid Build Coastguard Worker 	  else
811*7304104dSAndroid Build Coastguard Worker 	    {
812*7304104dSAndroid Build Coastguard Worker 	      char *fieldname = runp->field->name;
813*7304104dSAndroid Build Coastguard Worker 
814*7304104dSAndroid Build Coastguard Worker 	      struct synonym search = { .from = fieldname };
815*7304104dSAndroid Build Coastguard Worker 
816*7304104dSAndroid Build Coastguard Worker 	      struct synonym **res = tfind (&search, &synonyms, compare_syn);
817*7304104dSAndroid Build Coastguard Worker 	      if (res != NULL)
818*7304104dSAndroid Build Coastguard Worker 		fieldname = (*res)->to;
819*7304104dSAndroid Build Coastguard Worker 
820*7304104dSAndroid Build Coastguard Worker 	      obstack_grow_str (&ob, fieldname);
821*7304104dSAndroid Build Coastguard Worker 	    }
822*7304104dSAndroid Build Coastguard Worker 
823*7304104dSAndroid Build Coastguard Worker 	  /* Now compute the bit offset of the field.  */
824*7304104dSAndroid Build Coastguard Worker 	  struct bitvalue *b = bytes;
825*7304104dSAndroid Build Coastguard Worker 	  int bitoff = 0;
826*7304104dSAndroid Build Coastguard Worker 	  if (runp->field != NULL)
827*7304104dSAndroid Build Coastguard Worker 	    while (b != NULL)
828*7304104dSAndroid Build Coastguard Worker 	      {
829*7304104dSAndroid Build Coastguard Worker 		if (b->type == field && b->field != NULL)
830*7304104dSAndroid Build Coastguard Worker 		  {
831*7304104dSAndroid Build Coastguard Worker 		    if (strcmp (b->field->name, runp->field->name) == 0)
832*7304104dSAndroid Build Coastguard Worker 		      break;
833*7304104dSAndroid Build Coastguard Worker 		    bitoff += b->field->bits;
834*7304104dSAndroid Build Coastguard Worker 		  }
835*7304104dSAndroid Build Coastguard Worker 		else
836*7304104dSAndroid Build Coastguard Worker 		  ++bitoff;
837*7304104dSAndroid Build Coastguard Worker 
838*7304104dSAndroid Build Coastguard Worker 		b = b->next;
839*7304104dSAndroid Build Coastguard Worker 	      }
840*7304104dSAndroid Build Coastguard Worker 	  if (instr->operands[n].off1 == 0)
841*7304104dSAndroid Build Coastguard Worker 	    instr->operands[n].off1 = bitoff;
842*7304104dSAndroid Build Coastguard Worker 	  else if (instr->operands[n].off2 == 0)
843*7304104dSAndroid Build Coastguard Worker 	    instr->operands[n].off2 = bitoff;
844*7304104dSAndroid Build Coastguard Worker 	  else if (instr->operands[n].off3 == 0)
845*7304104dSAndroid Build Coastguard Worker 	    instr->operands[n].off3 = bitoff;
846*7304104dSAndroid Build Coastguard Worker 	  else
847*7304104dSAndroid Build Coastguard Worker 	    error (EXIT_FAILURE, 0,
848*7304104dSAndroid Build Coastguard Worker 		   "%d: cannot have more than three fields in parameter",
849*7304104dSAndroid Build Coastguard Worker 		   i386_lineno - 1);
850*7304104dSAndroid Build Coastguard Worker 
851*7304104dSAndroid Build Coastguard Worker 	  if  (runp->field != NULL
852*7304104dSAndroid Build Coastguard Worker 	       && strncasecmp (runp->field->name, "mod", 3) == 0)
853*7304104dSAndroid Build Coastguard Worker 	    instr->modrm = 1;
854*7304104dSAndroid Build Coastguard Worker 	}
855*7304104dSAndroid Build Coastguard Worker 
856*7304104dSAndroid Build Coastguard Worker       runp = runp->next;
857*7304104dSAndroid Build Coastguard Worker     }
858*7304104dSAndroid Build Coastguard Worker   if (obstack_object_size (&ob) == 0)
859*7304104dSAndroid Build Coastguard Worker     obstack_grow_str (&ob, "string");
860*7304104dSAndroid Build Coastguard Worker   obstack_1grow (&ob, '\0');
861*7304104dSAndroid Build Coastguard Worker   char *fct = obstack_finish (&ob);
862*7304104dSAndroid Build Coastguard Worker 
863*7304104dSAndroid Build Coastguard Worker   instr->operands[n].fct = fct;
864*7304104dSAndroid Build Coastguard Worker }
865*7304104dSAndroid Build Coastguard Worker 
866*7304104dSAndroid Build Coastguard Worker 
867*7304104dSAndroid Build Coastguard Worker #if 0
868*7304104dSAndroid Build Coastguard Worker static void
869*7304104dSAndroid Build Coastguard Worker nameout (const void *nodep, VISIT value, int level)
870*7304104dSAndroid Build Coastguard Worker {
871*7304104dSAndroid Build Coastguard Worker   if (value == leaf || value == postorder)
872*7304104dSAndroid Build Coastguard Worker     printf ("  %s\n", *(const char **) nodep);
873*7304104dSAndroid Build Coastguard Worker }
874*7304104dSAndroid Build Coastguard Worker #endif
875*7304104dSAndroid Build Coastguard Worker 
876*7304104dSAndroid Build Coastguard Worker 
877*7304104dSAndroid Build Coastguard Worker static int
compare_argstring(const void * p1,const void * p2)878*7304104dSAndroid Build Coastguard Worker compare_argstring (const void *p1, const void *p2)
879*7304104dSAndroid Build Coastguard Worker {
880*7304104dSAndroid Build Coastguard Worker   const struct argstring *a1 = (const struct argstring *) p1;
881*7304104dSAndroid Build Coastguard Worker   const struct argstring *a2 = (const struct argstring *) p2;
882*7304104dSAndroid Build Coastguard Worker 
883*7304104dSAndroid Build Coastguard Worker   return strcmp (a1->str, a2->str);
884*7304104dSAndroid Build Coastguard Worker }
885*7304104dSAndroid Build Coastguard Worker 
886*7304104dSAndroid Build Coastguard Worker 
887*7304104dSAndroid Build Coastguard Worker static int maxoff[3][3];
888*7304104dSAndroid Build Coastguard Worker static int minoff[3][3] = { { 1000, 1000, 1000 },
889*7304104dSAndroid Build Coastguard Worker 			    { 1000, 1000, 1000 },
890*7304104dSAndroid Build Coastguard Worker 			    { 1000, 1000, 1000 } };
891*7304104dSAndroid Build Coastguard Worker static int nbitoff[3][3];
892*7304104dSAndroid Build Coastguard Worker static void *fct_names[3];
893*7304104dSAndroid Build Coastguard Worker static int nbitfct[3];
894*7304104dSAndroid Build Coastguard Worker static int nbitsuf;
895*7304104dSAndroid Build Coastguard Worker static void *strs[3];
896*7304104dSAndroid Build Coastguard Worker static int nbitstr[3];
897*7304104dSAndroid Build Coastguard Worker static int total_bits = 2;	// Already counted the rep/repe bits.
898*7304104dSAndroid Build Coastguard Worker 
899*7304104dSAndroid Build Coastguard Worker static void
find_numbers(void)900*7304104dSAndroid Build Coastguard Worker find_numbers (void)
901*7304104dSAndroid Build Coastguard Worker {
902*7304104dSAndroid Build Coastguard Worker   int nfct_names[3] = { 0, 0, 0 };
903*7304104dSAndroid Build Coastguard Worker   int nstrs[3] = { 0, 0, 0 };
904*7304104dSAndroid Build Coastguard Worker 
905*7304104dSAndroid Build Coastguard Worker   /* We reverse the order of the instruction list while processing it.
906*7304104dSAndroid Build Coastguard Worker      Later phases need it in the order in which the input file has
907*7304104dSAndroid Build Coastguard Worker      them.  */
908*7304104dSAndroid Build Coastguard Worker   struct instruction *reversed = NULL;
909*7304104dSAndroid Build Coastguard Worker 
910*7304104dSAndroid Build Coastguard Worker   struct instruction *runp = instructions;
911*7304104dSAndroid Build Coastguard Worker   while (runp != NULL)
912*7304104dSAndroid Build Coastguard Worker     {
913*7304104dSAndroid Build Coastguard Worker       for (int i = 0; i < 3; ++i)
914*7304104dSAndroid Build Coastguard Worker 	if (runp->operands[i].fct != NULL)
915*7304104dSAndroid Build Coastguard Worker 	  {
916*7304104dSAndroid Build Coastguard Worker 	    struct argstring search = { .str = runp->operands[i].fct };
917*7304104dSAndroid Build Coastguard Worker 	    if (tfind (&search, &fct_names[i], compare_argstring) == NULL)
918*7304104dSAndroid Build Coastguard Worker 	      {
919*7304104dSAndroid Build Coastguard Worker 		struct argstring *newp = xmalloc (sizeof (*newp));
920*7304104dSAndroid Build Coastguard Worker 		newp->str = runp->operands[i].fct;
921*7304104dSAndroid Build Coastguard Worker 		newp->idx = 0;
922*7304104dSAndroid Build Coastguard Worker 		if (tsearch (newp, &fct_names[i], compare_argstring) == NULL)
923*7304104dSAndroid Build Coastguard Worker 		  error (EXIT_FAILURE, errno, "tsearch");
924*7304104dSAndroid Build Coastguard Worker 		++nfct_names[i];
925*7304104dSAndroid Build Coastguard Worker 	      }
926*7304104dSAndroid Build Coastguard Worker 
927*7304104dSAndroid Build Coastguard Worker 	    if (runp->operands[i].str != NULL)
928*7304104dSAndroid Build Coastguard Worker 	      {
929*7304104dSAndroid Build Coastguard Worker 		search.str = runp->operands[i].str;
930*7304104dSAndroid Build Coastguard Worker 		if (tfind (&search, &strs[i], compare_argstring) == NULL)
931*7304104dSAndroid Build Coastguard Worker 		  {
932*7304104dSAndroid Build Coastguard Worker 		    struct argstring *newp = xmalloc (sizeof (*newp));
933*7304104dSAndroid Build Coastguard Worker 		    newp->str = runp->operands[i].str;
934*7304104dSAndroid Build Coastguard Worker 		    newp->idx = 0;
935*7304104dSAndroid Build Coastguard Worker 		    if (tsearch (newp, &strs[i], compare_argstring) == NULL)
936*7304104dSAndroid Build Coastguard Worker 		      error (EXIT_FAILURE, errno, "tsearch");
937*7304104dSAndroid Build Coastguard Worker 		    ++nstrs[i];
938*7304104dSAndroid Build Coastguard Worker 		  }
939*7304104dSAndroid Build Coastguard Worker 	      }
940*7304104dSAndroid Build Coastguard Worker 
941*7304104dSAndroid Build Coastguard Worker 	    maxoff[i][0] = MAX (maxoff[i][0], runp->operands[i].off1);
942*7304104dSAndroid Build Coastguard Worker 	    maxoff[i][1] = MAX (maxoff[i][1], runp->operands[i].off2);
943*7304104dSAndroid Build Coastguard Worker 	    maxoff[i][2] = MAX (maxoff[i][2], runp->operands[i].off3);
944*7304104dSAndroid Build Coastguard Worker 
945*7304104dSAndroid Build Coastguard Worker 	    if (runp->operands[i].off1 > 0)
946*7304104dSAndroid Build Coastguard Worker 	      minoff[i][0] = MIN (minoff[i][0], runp->operands[i].off1);
947*7304104dSAndroid Build Coastguard Worker 	    if (runp->operands[i].off2 > 0)
948*7304104dSAndroid Build Coastguard Worker 	      minoff[i][1] = MIN (minoff[i][1], runp->operands[i].off2);
949*7304104dSAndroid Build Coastguard Worker 	    if (runp->operands[i].off3 > 0)
950*7304104dSAndroid Build Coastguard Worker 	      minoff[i][2] = MIN (minoff[i][2], runp->operands[i].off3);
951*7304104dSAndroid Build Coastguard Worker 	  }
952*7304104dSAndroid Build Coastguard Worker 
953*7304104dSAndroid Build Coastguard Worker       struct instruction *old = runp;
954*7304104dSAndroid Build Coastguard Worker       runp = runp->next;
955*7304104dSAndroid Build Coastguard Worker 
956*7304104dSAndroid Build Coastguard Worker       old->next = reversed;
957*7304104dSAndroid Build Coastguard Worker       reversed = old;
958*7304104dSAndroid Build Coastguard Worker     }
959*7304104dSAndroid Build Coastguard Worker   instructions = reversed;
960*7304104dSAndroid Build Coastguard Worker 
961*7304104dSAndroid Build Coastguard Worker   int d;
962*7304104dSAndroid Build Coastguard Worker   int c;
963*7304104dSAndroid Build Coastguard Worker   for (int i = 0; i < 3; ++i)
964*7304104dSAndroid Build Coastguard Worker     {
965*7304104dSAndroid Build Coastguard Worker       // printf ("min1 = %d, min2 = %d, min3 = %d\n", minoff[i][0], minoff[i][1], minoff[i][2]);
966*7304104dSAndroid Build Coastguard Worker       // printf ("max1 = %d, max2 = %d, max3 = %d\n", maxoff[i][0], maxoff[i][1], maxoff[i][2]);
967*7304104dSAndroid Build Coastguard Worker 
968*7304104dSAndroid Build Coastguard Worker       if (minoff[i][0] == 1000)
969*7304104dSAndroid Build Coastguard Worker 	nbitoff[i][0] = 0;
970*7304104dSAndroid Build Coastguard Worker       else
971*7304104dSAndroid Build Coastguard Worker 	{
972*7304104dSAndroid Build Coastguard Worker 	  nbitoff[i][0] = 1;
973*7304104dSAndroid Build Coastguard Worker 	  d = maxoff[i][0] - minoff[i][0];
974*7304104dSAndroid Build Coastguard Worker 	  c = 1;
975*7304104dSAndroid Build Coastguard Worker 	  while (c < d)
976*7304104dSAndroid Build Coastguard Worker 	    {
977*7304104dSAndroid Build Coastguard Worker 	      ++nbitoff[i][0];
978*7304104dSAndroid Build Coastguard Worker 	      c *= 2;
979*7304104dSAndroid Build Coastguard Worker 	    }
980*7304104dSAndroid Build Coastguard Worker 	  total_bits += nbitoff[i][0];
981*7304104dSAndroid Build Coastguard Worker 	}
982*7304104dSAndroid Build Coastguard Worker 
983*7304104dSAndroid Build Coastguard Worker       if (minoff[i][1] == 1000)
984*7304104dSAndroid Build Coastguard Worker 	nbitoff[i][1] = 0;
985*7304104dSAndroid Build Coastguard Worker       else
986*7304104dSAndroid Build Coastguard Worker 	{
987*7304104dSAndroid Build Coastguard Worker 	  nbitoff[i][1] = 1;
988*7304104dSAndroid Build Coastguard Worker 	  d = maxoff[i][1] - minoff[i][1];
989*7304104dSAndroid Build Coastguard Worker 	  c = 1;
990*7304104dSAndroid Build Coastguard Worker 	  while (c < d)
991*7304104dSAndroid Build Coastguard Worker 	    {
992*7304104dSAndroid Build Coastguard Worker 	      ++nbitoff[i][1];
993*7304104dSAndroid Build Coastguard Worker 	      c *= 2;
994*7304104dSAndroid Build Coastguard Worker 	    }
995*7304104dSAndroid Build Coastguard Worker 	  total_bits += nbitoff[i][1];
996*7304104dSAndroid Build Coastguard Worker 	}
997*7304104dSAndroid Build Coastguard Worker 
998*7304104dSAndroid Build Coastguard Worker       if (minoff[i][2] == 1000)
999*7304104dSAndroid Build Coastguard Worker 	nbitoff[i][2] = 0;
1000*7304104dSAndroid Build Coastguard Worker       else
1001*7304104dSAndroid Build Coastguard Worker 	{
1002*7304104dSAndroid Build Coastguard Worker 	  nbitoff[i][2] = 1;
1003*7304104dSAndroid Build Coastguard Worker 	  d = maxoff[i][2] - minoff[i][2];
1004*7304104dSAndroid Build Coastguard Worker 	  c = 1;
1005*7304104dSAndroid Build Coastguard Worker 	  while (c < d)
1006*7304104dSAndroid Build Coastguard Worker 	    {
1007*7304104dSAndroid Build Coastguard Worker 	      ++nbitoff[i][2];
1008*7304104dSAndroid Build Coastguard Worker 	      c *= 2;
1009*7304104dSAndroid Build Coastguard Worker 	    }
1010*7304104dSAndroid Build Coastguard Worker 	  total_bits += nbitoff[i][2];
1011*7304104dSAndroid Build Coastguard Worker 	}
1012*7304104dSAndroid Build Coastguard Worker       // printf ("off1 = %d, off2 = %d, off3 = %d\n", nbitoff[i][0], nbitoff[i][1], nbitoff[i][2]);
1013*7304104dSAndroid Build Coastguard Worker 
1014*7304104dSAndroid Build Coastguard Worker       nbitfct[i] = 1;
1015*7304104dSAndroid Build Coastguard Worker       d = nfct_names[i];
1016*7304104dSAndroid Build Coastguard Worker       c = 1;
1017*7304104dSAndroid Build Coastguard Worker       while (c < d)
1018*7304104dSAndroid Build Coastguard Worker 	{
1019*7304104dSAndroid Build Coastguard Worker 	  ++nbitfct[i];
1020*7304104dSAndroid Build Coastguard Worker 	  c *= 2;
1021*7304104dSAndroid Build Coastguard Worker 	}
1022*7304104dSAndroid Build Coastguard Worker       total_bits += nbitfct[i];
1023*7304104dSAndroid Build Coastguard Worker       // printf ("%d fct[%d], %d bits\n", nfct_names[i], i, nbitfct[i]);
1024*7304104dSAndroid Build Coastguard Worker 
1025*7304104dSAndroid Build Coastguard Worker       if (nstrs[i] != 0)
1026*7304104dSAndroid Build Coastguard Worker 	{
1027*7304104dSAndroid Build Coastguard Worker 	  nbitstr[i] = 1;
1028*7304104dSAndroid Build Coastguard Worker 	  d = nstrs[i];
1029*7304104dSAndroid Build Coastguard Worker 	  c = 1;
1030*7304104dSAndroid Build Coastguard Worker 	  while (c < d)
1031*7304104dSAndroid Build Coastguard Worker 	    {
1032*7304104dSAndroid Build Coastguard Worker 	      ++nbitstr[i];
1033*7304104dSAndroid Build Coastguard Worker 	      c *= 2;
1034*7304104dSAndroid Build Coastguard Worker 	    }
1035*7304104dSAndroid Build Coastguard Worker 	  total_bits += nbitstr[i];
1036*7304104dSAndroid Build Coastguard Worker 	}
1037*7304104dSAndroid Build Coastguard Worker 
1038*7304104dSAndroid Build Coastguard Worker       // twalk (fct_names[i], nameout);
1039*7304104dSAndroid Build Coastguard Worker     }
1040*7304104dSAndroid Build Coastguard Worker 
1041*7304104dSAndroid Build Coastguard Worker   nbitsuf = 0;
1042*7304104dSAndroid Build Coastguard Worker   d = nsuffixes;
1043*7304104dSAndroid Build Coastguard Worker   c = 1;
1044*7304104dSAndroid Build Coastguard Worker   while (c < d)
1045*7304104dSAndroid Build Coastguard Worker     {
1046*7304104dSAndroid Build Coastguard Worker       ++nbitsuf;
1047*7304104dSAndroid Build Coastguard Worker       c *= 2;
1048*7304104dSAndroid Build Coastguard Worker     }
1049*7304104dSAndroid Build Coastguard Worker   total_bits += nbitsuf;
1050*7304104dSAndroid Build Coastguard Worker   // printf ("%d suffixes, %d bits\n", nsuffixes, nbitsuf);
1051*7304104dSAndroid Build Coastguard Worker }
1052*7304104dSAndroid Build Coastguard Worker 
1053*7304104dSAndroid Build Coastguard Worker 
1054*7304104dSAndroid Build Coastguard Worker static int
compare_syn(const void * p1,const void * p2)1055*7304104dSAndroid Build Coastguard Worker compare_syn (const void *p1, const void *p2)
1056*7304104dSAndroid Build Coastguard Worker {
1057*7304104dSAndroid Build Coastguard Worker   const struct synonym *s1 = (const struct synonym *) p1;
1058*7304104dSAndroid Build Coastguard Worker   const struct synonym *s2 = (const struct synonym *) p2;
1059*7304104dSAndroid Build Coastguard Worker 
1060*7304104dSAndroid Build Coastguard Worker   return strcmp (s1->from, s2->from);
1061*7304104dSAndroid Build Coastguard Worker }
1062*7304104dSAndroid Build Coastguard Worker 
1063*7304104dSAndroid Build Coastguard Worker 
1064*7304104dSAndroid Build Coastguard Worker static int
compare_suf(const void * p1,const void * p2)1065*7304104dSAndroid Build Coastguard Worker compare_suf (const void *p1, const void *p2)
1066*7304104dSAndroid Build Coastguard Worker {
1067*7304104dSAndroid Build Coastguard Worker   const struct suffix *s1 = (const struct suffix *) p1;
1068*7304104dSAndroid Build Coastguard Worker   const struct suffix *s2 = (const struct suffix *) p2;
1069*7304104dSAndroid Build Coastguard Worker 
1070*7304104dSAndroid Build Coastguard Worker   return strcmp (s1->name, s2->name);
1071*7304104dSAndroid Build Coastguard Worker }
1072*7304104dSAndroid Build Coastguard Worker 
1073*7304104dSAndroid Build Coastguard Worker 
1074*7304104dSAndroid Build Coastguard Worker static int count_op_str;
1075*7304104dSAndroid Build Coastguard Worker static int off_op_str;
1076*7304104dSAndroid Build Coastguard Worker static void
print_op_str(const void * nodep,VISIT value,int level)1077*7304104dSAndroid Build Coastguard Worker print_op_str (const void *nodep, VISIT value,
1078*7304104dSAndroid Build Coastguard Worker 	      int level __attribute__ ((unused)))
1079*7304104dSAndroid Build Coastguard Worker {
1080*7304104dSAndroid Build Coastguard Worker   if (value == leaf || value == postorder)
1081*7304104dSAndroid Build Coastguard Worker     {
1082*7304104dSAndroid Build Coastguard Worker       const char *str = (*(struct argstring **) nodep)->str;
1083*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, "%s\n  \"%s",
1084*7304104dSAndroid Build Coastguard Worker 	       count_op_str == 0 ? "" : "\\0\"", str);
1085*7304104dSAndroid Build Coastguard Worker       (*(struct argstring **) nodep)->idx = ++count_op_str;
1086*7304104dSAndroid Build Coastguard Worker       (*(struct argstring **) nodep)->off = off_op_str;
1087*7304104dSAndroid Build Coastguard Worker       off_op_str += strlen (str) + 1;
1088*7304104dSAndroid Build Coastguard Worker     }
1089*7304104dSAndroid Build Coastguard Worker }
1090*7304104dSAndroid Build Coastguard Worker 
1091*7304104dSAndroid Build Coastguard Worker 
1092*7304104dSAndroid Build Coastguard Worker static void
print_op_str_idx(const void * nodep,VISIT value,int level)1093*7304104dSAndroid Build Coastguard Worker print_op_str_idx (const void *nodep, VISIT value,
1094*7304104dSAndroid Build Coastguard Worker 		  int level __attribute__ ((unused)))
1095*7304104dSAndroid Build Coastguard Worker {
1096*7304104dSAndroid Build Coastguard Worker   if (value == leaf || value == postorder)
1097*7304104dSAndroid Build Coastguard Worker     printf ("  %d,\n", (*(struct argstring **) nodep)->off);
1098*7304104dSAndroid Build Coastguard Worker }
1099*7304104dSAndroid Build Coastguard Worker 
1100*7304104dSAndroid Build Coastguard Worker 
1101*7304104dSAndroid Build Coastguard Worker static void
print_op_fct(const void * nodep,VISIT value,int level)1102*7304104dSAndroid Build Coastguard Worker print_op_fct (const void *nodep, VISIT value,
1103*7304104dSAndroid Build Coastguard Worker 	      int level __attribute__ ((unused)))
1104*7304104dSAndroid Build Coastguard Worker {
1105*7304104dSAndroid Build Coastguard Worker   if (value == leaf || value == postorder)
1106*7304104dSAndroid Build Coastguard Worker     {
1107*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, "  FCT_%s,\n", (*(struct argstring **) nodep)->str);
1108*7304104dSAndroid Build Coastguard Worker       (*(struct argstring **) nodep)->idx = ++count_op_str;
1109*7304104dSAndroid Build Coastguard Worker     }
1110*7304104dSAndroid Build Coastguard Worker }
1111*7304104dSAndroid Build Coastguard Worker 
1112*7304104dSAndroid Build Coastguard Worker static void
instrtable_out(void)1113*7304104dSAndroid Build Coastguard Worker instrtable_out (void)
1114*7304104dSAndroid Build Coastguard Worker {
1115*7304104dSAndroid Build Coastguard Worker   find_numbers ();
1116*7304104dSAndroid Build Coastguard Worker 
1117*7304104dSAndroid Build Coastguard Worker #if 0
1118*7304104dSAndroid Build Coastguard Worker   create_mnemonic_table ();
1119*7304104dSAndroid Build Coastguard Worker 
1120*7304104dSAndroid Build Coastguard Worker   fprintf (outfile, "#define MNEMONIC_BITS %zu\n", best_mnemonic_bits);
1121*7304104dSAndroid Build Coastguard Worker #else
1122*7304104dSAndroid Build Coastguard Worker   fprintf (outfile, "#define MNEMONIC_BITS %ld\n",
1123*7304104dSAndroid Build Coastguard Worker 	   lrint (ceil (log2 (MNE_COUNT))));
1124*7304104dSAndroid Build Coastguard Worker #endif
1125*7304104dSAndroid Build Coastguard Worker   fprintf (outfile, "#define SUFFIX_BITS %d\n", nbitsuf);
1126*7304104dSAndroid Build Coastguard Worker   for (int i = 0; i < 3; ++i)
1127*7304104dSAndroid Build Coastguard Worker     {
1128*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, "#define FCT%d_BITS %d\n", i + 1, nbitfct[i]);
1129*7304104dSAndroid Build Coastguard Worker       if (nbitstr[i] != 0)
1130*7304104dSAndroid Build Coastguard Worker 	fprintf (outfile, "#define STR%d_BITS %d\n", i + 1, nbitstr[i]);
1131*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, "#define OFF%d_1_BITS %d\n", i + 1, nbitoff[i][0]);
1132*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, "#define OFF%d_1_BIAS %d\n", i + 1, minoff[i][0]);
1133*7304104dSAndroid Build Coastguard Worker       if (nbitoff[i][1] != 0)
1134*7304104dSAndroid Build Coastguard Worker 	{
1135*7304104dSAndroid Build Coastguard Worker 	  fprintf (outfile, "#define OFF%d_2_BITS %d\n", i + 1, nbitoff[i][1]);
1136*7304104dSAndroid Build Coastguard Worker 	  fprintf (outfile, "#define OFF%d_2_BIAS %d\n", i + 1, minoff[i][1]);
1137*7304104dSAndroid Build Coastguard Worker 	}
1138*7304104dSAndroid Build Coastguard Worker       if (nbitoff[i][2] != 0)
1139*7304104dSAndroid Build Coastguard Worker 	{
1140*7304104dSAndroid Build Coastguard Worker 	  fprintf (outfile, "#define OFF%d_3_BITS %d\n", i + 1, nbitoff[i][2]);
1141*7304104dSAndroid Build Coastguard Worker 	  fprintf (outfile, "#define OFF%d_3_BIAS %d\n", i + 1, minoff[i][2]);
1142*7304104dSAndroid Build Coastguard Worker 	}
1143*7304104dSAndroid Build Coastguard Worker     }
1144*7304104dSAndroid Build Coastguard Worker 
1145*7304104dSAndroid Build Coastguard Worker   fputs ("\n#include <i386_data.h>\n\n", outfile);
1146*7304104dSAndroid Build Coastguard Worker 
1147*7304104dSAndroid Build Coastguard Worker 
1148*7304104dSAndroid Build Coastguard Worker #define APPEND(a, b) APPEND_ (a, b)
1149*7304104dSAndroid Build Coastguard Worker #define APPEND_(a, b) a##b
1150*7304104dSAndroid Build Coastguard Worker #define EMIT_SUFFIX(suf) \
1151*7304104dSAndroid Build Coastguard Worker   fprintf (outfile, "#define suffix_%s %d\n", #suf, APPEND (suffix_, suf))
1152*7304104dSAndroid Build Coastguard Worker   EMIT_SUFFIX (none);
1153*7304104dSAndroid Build Coastguard Worker   EMIT_SUFFIX (w);
1154*7304104dSAndroid Build Coastguard Worker   EMIT_SUFFIX (w0);
1155*7304104dSAndroid Build Coastguard Worker   EMIT_SUFFIX (W);
1156*7304104dSAndroid Build Coastguard Worker   EMIT_SUFFIX (tttn);
1157*7304104dSAndroid Build Coastguard Worker   EMIT_SUFFIX (D);
1158*7304104dSAndroid Build Coastguard Worker   EMIT_SUFFIX (w1);
1159*7304104dSAndroid Build Coastguard Worker   EMIT_SUFFIX (W1);
1160*7304104dSAndroid Build Coastguard Worker 
1161*7304104dSAndroid Build Coastguard Worker   fputc_unlocked ('\n', outfile);
1162*7304104dSAndroid Build Coastguard Worker 
1163*7304104dSAndroid Build Coastguard Worker   for (int i = 0; i < 3; ++i)
1164*7304104dSAndroid Build Coastguard Worker     {
1165*7304104dSAndroid Build Coastguard Worker       /* Functions.  */
1166*7304104dSAndroid Build Coastguard Worker       count_op_str = 0;
1167*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, "static const opfct_t op%d_fct[] =\n{\n  NULL,\n",
1168*7304104dSAndroid Build Coastguard Worker 	       i + 1);
1169*7304104dSAndroid Build Coastguard Worker       twalk (fct_names[i], print_op_fct);
1170*7304104dSAndroid Build Coastguard Worker       fputs ("};\n", outfile);
1171*7304104dSAndroid Build Coastguard Worker 
1172*7304104dSAndroid Build Coastguard Worker       /* The operand strings.  */
1173*7304104dSAndroid Build Coastguard Worker       if (nbitstr[i] != 0)
1174*7304104dSAndroid Build Coastguard Worker 	{
1175*7304104dSAndroid Build Coastguard Worker 	  count_op_str = 0;
1176*7304104dSAndroid Build Coastguard Worker 	  off_op_str = 0;
1177*7304104dSAndroid Build Coastguard Worker 	  fprintf (outfile, "static const char op%d_str[] =", i + 1);
1178*7304104dSAndroid Build Coastguard Worker 	  twalk (strs[i], print_op_str);
1179*7304104dSAndroid Build Coastguard Worker 	  fputs ("\";\n", outfile);
1180*7304104dSAndroid Build Coastguard Worker 
1181*7304104dSAndroid Build Coastguard Worker 	  fprintf (outfile, "static const uint8_t op%d_str_idx[] = {\n",
1182*7304104dSAndroid Build Coastguard Worker 		   i + 1);
1183*7304104dSAndroid Build Coastguard Worker 	  twalk (strs[i], print_op_str_idx);
1184*7304104dSAndroid Build Coastguard Worker 	  fputs ("};\n", outfile);
1185*7304104dSAndroid Build Coastguard Worker 	}
1186*7304104dSAndroid Build Coastguard Worker     }
1187*7304104dSAndroid Build Coastguard Worker 
1188*7304104dSAndroid Build Coastguard Worker 
1189*7304104dSAndroid Build Coastguard Worker   fputs ("static const struct instr_enc instrtab[] =\n{\n", outfile);
1190*7304104dSAndroid Build Coastguard Worker   struct instruction *instr;
1191*7304104dSAndroid Build Coastguard Worker   for (instr = instructions; instr != NULL; instr = instr->next)
1192*7304104dSAndroid Build Coastguard Worker     {
1193*7304104dSAndroid Build Coastguard Worker       fputs ("  {", outfile);
1194*7304104dSAndroid Build Coastguard Worker       if (instr->mnemonic == (void *) -1l)
1195*7304104dSAndroid Build Coastguard Worker 	fputs (" .mnemonic = MNE_INVALID,", outfile);
1196*7304104dSAndroid Build Coastguard Worker       else
1197*7304104dSAndroid Build Coastguard Worker 	fprintf (outfile, " .mnemonic = MNE_%s,", instr->mnemonic);
1198*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, " .rep = %d,", instr->rep);
1199*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, " .repe = %d,", instr->repe);
1200*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, " .suffix = %d,", instr->suffix);
1201*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, " .modrm = %d,", instr->modrm);
1202*7304104dSAndroid Build Coastguard Worker 
1203*7304104dSAndroid Build Coastguard Worker       for (int i = 0; i < 3; ++i)
1204*7304104dSAndroid Build Coastguard Worker 	{
1205*7304104dSAndroid Build Coastguard Worker 	  int idx = 0;
1206*7304104dSAndroid Build Coastguard Worker 	  if (instr->operands[i].fct != NULL)
1207*7304104dSAndroid Build Coastguard Worker 	    {
1208*7304104dSAndroid Build Coastguard Worker 	      struct argstring search = { .str = instr->operands[i].fct };
1209*7304104dSAndroid Build Coastguard Worker 	      struct argstring **res = tfind (&search, &fct_names[i],
1210*7304104dSAndroid Build Coastguard Worker 					      compare_argstring);
1211*7304104dSAndroid Build Coastguard Worker 	      assert (res != NULL);
1212*7304104dSAndroid Build Coastguard Worker 	      idx = (*res)->idx;
1213*7304104dSAndroid Build Coastguard Worker 	    }
1214*7304104dSAndroid Build Coastguard Worker 	  fprintf (outfile, " .fct%d = %d,", i + 1, idx);
1215*7304104dSAndroid Build Coastguard Worker 
1216*7304104dSAndroid Build Coastguard Worker 	  idx = 0;
1217*7304104dSAndroid Build Coastguard Worker 	  if (instr->operands[i].str != NULL)
1218*7304104dSAndroid Build Coastguard Worker 	    {
1219*7304104dSAndroid Build Coastguard Worker 	      struct argstring search = { .str = instr->operands[i].str };
1220*7304104dSAndroid Build Coastguard Worker 	      struct argstring **res = tfind (&search, &strs[i],
1221*7304104dSAndroid Build Coastguard Worker 					      compare_argstring);
1222*7304104dSAndroid Build Coastguard Worker 	      assert (res != NULL);
1223*7304104dSAndroid Build Coastguard Worker 	      idx = (*res)->idx;
1224*7304104dSAndroid Build Coastguard Worker 	    }
1225*7304104dSAndroid Build Coastguard Worker 	  if (nbitstr[i] != 0)
1226*7304104dSAndroid Build Coastguard Worker 	    fprintf (outfile, " .str%d = %d,", i + 1, idx);
1227*7304104dSAndroid Build Coastguard Worker 
1228*7304104dSAndroid Build Coastguard Worker 	  fprintf (outfile, " .off%d_1 = %d,", i + 1,
1229*7304104dSAndroid Build Coastguard Worker 		   MAX (0, instr->operands[i].off1 - minoff[i][0]));
1230*7304104dSAndroid Build Coastguard Worker 
1231*7304104dSAndroid Build Coastguard Worker 	  if (nbitoff[i][1] != 0)
1232*7304104dSAndroid Build Coastguard Worker 	    fprintf (outfile, " .off%d_2 = %d,", i + 1,
1233*7304104dSAndroid Build Coastguard Worker 		     MAX (0, instr->operands[i].off2 - minoff[i][1]));
1234*7304104dSAndroid Build Coastguard Worker 
1235*7304104dSAndroid Build Coastguard Worker 	  if (nbitoff[i][2] != 0)
1236*7304104dSAndroid Build Coastguard Worker 	    fprintf (outfile, " .off%d_3 = %d,", i + 1,
1237*7304104dSAndroid Build Coastguard Worker 		     MAX (0, instr->operands[i].off3 - minoff[i][2]));
1238*7304104dSAndroid Build Coastguard Worker 	}
1239*7304104dSAndroid Build Coastguard Worker 
1240*7304104dSAndroid Build Coastguard Worker       fputs (" },\n", outfile);
1241*7304104dSAndroid Build Coastguard Worker     }
1242*7304104dSAndroid Build Coastguard Worker   fputs ("};\n", outfile);
1243*7304104dSAndroid Build Coastguard Worker 
1244*7304104dSAndroid Build Coastguard Worker   fputs ("static const uint8_t match_data[] =\n{\n", outfile);
1245*7304104dSAndroid Build Coastguard Worker   size_t cnt = 0;
1246*7304104dSAndroid Build Coastguard Worker   for (instr = instructions; instr != NULL; instr = instr->next, ++cnt)
1247*7304104dSAndroid Build Coastguard Worker     {
1248*7304104dSAndroid Build Coastguard Worker       /* First count the number of bytes.  */
1249*7304104dSAndroid Build Coastguard Worker       size_t totalbits = 0;
1250*7304104dSAndroid Build Coastguard Worker       size_t zerobits = 0;
1251*7304104dSAndroid Build Coastguard Worker       bool leading_p = true;
1252*7304104dSAndroid Build Coastguard Worker       size_t leadingbits = 0;
1253*7304104dSAndroid Build Coastguard Worker       struct bitvalue *b = instr->bytes;
1254*7304104dSAndroid Build Coastguard Worker       while (b != NULL)
1255*7304104dSAndroid Build Coastguard Worker 	{
1256*7304104dSAndroid Build Coastguard Worker 	  if (b->type == zeroone)
1257*7304104dSAndroid Build Coastguard Worker 	    {
1258*7304104dSAndroid Build Coastguard Worker 	      ++totalbits;
1259*7304104dSAndroid Build Coastguard Worker 	      zerobits = 0;
1260*7304104dSAndroid Build Coastguard Worker 	      if (leading_p)
1261*7304104dSAndroid Build Coastguard Worker 		++leadingbits;
1262*7304104dSAndroid Build Coastguard Worker 	    }
1263*7304104dSAndroid Build Coastguard Worker 	  else
1264*7304104dSAndroid Build Coastguard Worker 	    {
1265*7304104dSAndroid Build Coastguard Worker 	      totalbits += b->field->bits;
1266*7304104dSAndroid Build Coastguard Worker 	      /* We must always count the mod/rm byte.  */
1267*7304104dSAndroid Build Coastguard Worker 	      if (strncasecmp (b->field->name, "mod", 3) == 0)
1268*7304104dSAndroid Build Coastguard Worker 		zerobits = 0;
1269*7304104dSAndroid Build Coastguard Worker 	      else
1270*7304104dSAndroid Build Coastguard Worker 		zerobits += b->field->bits;
1271*7304104dSAndroid Build Coastguard Worker 	      leading_p = false;
1272*7304104dSAndroid Build Coastguard Worker 	    }
1273*7304104dSAndroid Build Coastguard Worker 	  b = b->next;
1274*7304104dSAndroid Build Coastguard Worker 	}
1275*7304104dSAndroid Build Coastguard Worker       size_t nbytes = (totalbits - zerobits + 7) / 8;
1276*7304104dSAndroid Build Coastguard Worker       assert (nbytes > 0);
1277*7304104dSAndroid Build Coastguard Worker       size_t leadingbytes = leadingbits / 8;
1278*7304104dSAndroid Build Coastguard Worker 
1279*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, "  %#zx,", nbytes | (leadingbytes << 4));
1280*7304104dSAndroid Build Coastguard Worker 
1281*7304104dSAndroid Build Coastguard Worker       /* Now create the mask and byte values.  */
1282*7304104dSAndroid Build Coastguard Worker       uint8_t byte = 0;
1283*7304104dSAndroid Build Coastguard Worker       uint8_t mask = 0;
1284*7304104dSAndroid Build Coastguard Worker       int nbits = 0;
1285*7304104dSAndroid Build Coastguard Worker       b = instr->bytes;
1286*7304104dSAndroid Build Coastguard Worker       while (b != NULL)
1287*7304104dSAndroid Build Coastguard Worker 	{
1288*7304104dSAndroid Build Coastguard Worker 	  if (b->type == zeroone)
1289*7304104dSAndroid Build Coastguard Worker 	    {
1290*7304104dSAndroid Build Coastguard Worker 	      byte = (byte << 1) | b->value;
1291*7304104dSAndroid Build Coastguard Worker 	      mask = (mask << 1) | 1;
1292*7304104dSAndroid Build Coastguard Worker 	      if (++nbits == 8)
1293*7304104dSAndroid Build Coastguard Worker 		{
1294*7304104dSAndroid Build Coastguard Worker 		  if (leadingbytes > 0)
1295*7304104dSAndroid Build Coastguard Worker 		    {
1296*7304104dSAndroid Build Coastguard Worker 		      assert (mask == 0xff);
1297*7304104dSAndroid Build Coastguard Worker 		      fprintf (outfile, " %#" PRIx8 ",", byte);
1298*7304104dSAndroid Build Coastguard Worker 		      --leadingbytes;
1299*7304104dSAndroid Build Coastguard Worker 		    }
1300*7304104dSAndroid Build Coastguard Worker 		  else
1301*7304104dSAndroid Build Coastguard Worker 		    fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
1302*7304104dSAndroid Build Coastguard Worker 			     mask, byte);
1303*7304104dSAndroid Build Coastguard Worker 		  byte = mask = nbits = 0;
1304*7304104dSAndroid Build Coastguard Worker 		  if (--nbytes == 0)
1305*7304104dSAndroid Build Coastguard Worker 		    break;
1306*7304104dSAndroid Build Coastguard Worker 		}
1307*7304104dSAndroid Build Coastguard Worker 	    }
1308*7304104dSAndroid Build Coastguard Worker 	  else
1309*7304104dSAndroid Build Coastguard Worker 	    {
1310*7304104dSAndroid Build Coastguard Worker 	      assert (leadingbytes == 0);
1311*7304104dSAndroid Build Coastguard Worker 
1312*7304104dSAndroid Build Coastguard Worker 	      unsigned long int remaining = b->field->bits;
1313*7304104dSAndroid Build Coastguard Worker 	      while (nbits + remaining > 8)
1314*7304104dSAndroid Build Coastguard Worker 		{
1315*7304104dSAndroid Build Coastguard Worker 		  fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
1316*7304104dSAndroid Build Coastguard Worker 			   mask << (8 - nbits), byte << (8 - nbits));
1317*7304104dSAndroid Build Coastguard Worker 		  remaining = nbits + remaining - 8;
1318*7304104dSAndroid Build Coastguard Worker 		  byte = mask = nbits = 0;
1319*7304104dSAndroid Build Coastguard Worker 		  if (--nbytes == 0)
1320*7304104dSAndroid Build Coastguard Worker 		    break;
1321*7304104dSAndroid Build Coastguard Worker 		}
1322*7304104dSAndroid Build Coastguard Worker 	      byte <<= remaining;
1323*7304104dSAndroid Build Coastguard Worker 	      mask <<= remaining;
1324*7304104dSAndroid Build Coastguard Worker 	      nbits += remaining;
1325*7304104dSAndroid Build Coastguard Worker 	      if (nbits == 8)
1326*7304104dSAndroid Build Coastguard Worker 		{
1327*7304104dSAndroid Build Coastguard Worker 		  fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",", mask, byte);
1328*7304104dSAndroid Build Coastguard Worker 		  byte = mask = nbits = 0;
1329*7304104dSAndroid Build Coastguard Worker 		  if (--nbytes == 0)
1330*7304104dSAndroid Build Coastguard Worker 		    break;
1331*7304104dSAndroid Build Coastguard Worker 		}
1332*7304104dSAndroid Build Coastguard Worker 	    }
1333*7304104dSAndroid Build Coastguard Worker 	  b = b->next;
1334*7304104dSAndroid Build Coastguard Worker 	}
1335*7304104dSAndroid Build Coastguard Worker 
1336*7304104dSAndroid Build Coastguard Worker       fputc_unlocked ('\n', outfile);
1337*7304104dSAndroid Build Coastguard Worker     }
1338*7304104dSAndroid Build Coastguard Worker   fputs ("};\n", outfile);
1339*7304104dSAndroid Build Coastguard Worker }
1340*7304104dSAndroid Build Coastguard Worker 
1341*7304104dSAndroid Build Coastguard Worker 
1342*7304104dSAndroid Build Coastguard Worker #if 0
1343*7304104dSAndroid Build Coastguard Worker static size_t mnemonic_maxlen;
1344*7304104dSAndroid Build Coastguard Worker static size_t mnemonic_minlen;
1345*7304104dSAndroid Build Coastguard Worker static size_t
1346*7304104dSAndroid Build Coastguard Worker which_chars (const char *str[], size_t nstr)
1347*7304104dSAndroid Build Coastguard Worker {
1348*7304104dSAndroid Build Coastguard Worker   char used_char[256];
1349*7304104dSAndroid Build Coastguard Worker   memset (used_char, '\0', sizeof (used_char));
1350*7304104dSAndroid Build Coastguard Worker   mnemonic_maxlen = 0;
1351*7304104dSAndroid Build Coastguard Worker   mnemonic_minlen = 10000;
1352*7304104dSAndroid Build Coastguard Worker   for (size_t cnt = 0; cnt < nstr; ++cnt)
1353*7304104dSAndroid Build Coastguard Worker     {
1354*7304104dSAndroid Build Coastguard Worker       const unsigned char *cp = (const unsigned char *) str[cnt];
1355*7304104dSAndroid Build Coastguard Worker       mnemonic_maxlen = MAX (mnemonic_maxlen, strlen ((char *) cp));
1356*7304104dSAndroid Build Coastguard Worker       mnemonic_minlen = MIN (mnemonic_minlen, strlen ((char *) cp));
1357*7304104dSAndroid Build Coastguard Worker       do
1358*7304104dSAndroid Build Coastguard Worker         used_char[*cp++] = 1;
1359*7304104dSAndroid Build Coastguard Worker       while (*cp != '\0');
1360*7304104dSAndroid Build Coastguard Worker     }
1361*7304104dSAndroid Build Coastguard Worker   size_t nused_char = 0;
1362*7304104dSAndroid Build Coastguard Worker   for (size_t cnt = 0; cnt < 256; ++cnt)
1363*7304104dSAndroid Build Coastguard Worker     if (used_char[cnt] != 0)
1364*7304104dSAndroid Build Coastguard Worker       ++nused_char;
1365*7304104dSAndroid Build Coastguard Worker   return nused_char;
1366*7304104dSAndroid Build Coastguard Worker }
1367*7304104dSAndroid Build Coastguard Worker 
1368*7304104dSAndroid Build Coastguard Worker 
1369*7304104dSAndroid Build Coastguard Worker static const char **mnemonic_strs;
1370*7304104dSAndroid Build Coastguard Worker static size_t nmnemonic_strs;
1371*7304104dSAndroid Build Coastguard Worker static void
1372*7304104dSAndroid Build Coastguard Worker add_mnemonics (const void *nodep, VISIT value,
1373*7304104dSAndroid Build Coastguard Worker 	       int level __attribute__ ((unused)))
1374*7304104dSAndroid Build Coastguard Worker {
1375*7304104dSAndroid Build Coastguard Worker   if (value == leaf || value == postorder)
1376*7304104dSAndroid Build Coastguard Worker     mnemonic_strs[nmnemonic_strs++] = *(const char **) nodep;
1377*7304104dSAndroid Build Coastguard Worker }
1378*7304104dSAndroid Build Coastguard Worker 
1379*7304104dSAndroid Build Coastguard Worker 
1380*7304104dSAndroid Build Coastguard Worker struct charfreq
1381*7304104dSAndroid Build Coastguard Worker {
1382*7304104dSAndroid Build Coastguard Worker   char ch;
1383*7304104dSAndroid Build Coastguard Worker   int freq;
1384*7304104dSAndroid Build Coastguard Worker };
1385*7304104dSAndroid Build Coastguard Worker static struct charfreq pfxfreq[256];
1386*7304104dSAndroid Build Coastguard Worker static struct charfreq sfxfreq[256];
1387*7304104dSAndroid Build Coastguard Worker 
1388*7304104dSAndroid Build Coastguard Worker 
1389*7304104dSAndroid Build Coastguard Worker static int
1390*7304104dSAndroid Build Coastguard Worker compare_freq (const void *p1, const void *p2)
1391*7304104dSAndroid Build Coastguard Worker {
1392*7304104dSAndroid Build Coastguard Worker   const struct charfreq *c1 = (const struct charfreq *) p1;
1393*7304104dSAndroid Build Coastguard Worker   const struct charfreq *c2 = (const struct charfreq *) p2;
1394*7304104dSAndroid Build Coastguard Worker 
1395*7304104dSAndroid Build Coastguard Worker   if (c1->freq > c2->freq)
1396*7304104dSAndroid Build Coastguard Worker     return -1;
1397*7304104dSAndroid Build Coastguard Worker   if (c1->freq < c2->freq)
1398*7304104dSAndroid Build Coastguard Worker     return 1;
1399*7304104dSAndroid Build Coastguard Worker   return 0;
1400*7304104dSAndroid Build Coastguard Worker }
1401*7304104dSAndroid Build Coastguard Worker 
1402*7304104dSAndroid Build Coastguard Worker 
1403*7304104dSAndroid Build Coastguard Worker static size_t
1404*7304104dSAndroid Build Coastguard Worker compute_pfxfreq (const char *str[], size_t nstr)
1405*7304104dSAndroid Build Coastguard Worker {
1406*7304104dSAndroid Build Coastguard Worker   memset (pfxfreq, '\0', sizeof (pfxfreq));
1407*7304104dSAndroid Build Coastguard Worker 
1408*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nstr; ++i)
1409*7304104dSAndroid Build Coastguard Worker     pfxfreq[i].ch = i;
1410*7304104dSAndroid Build Coastguard Worker 
1411*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nstr; ++i)
1412*7304104dSAndroid Build Coastguard Worker     ++pfxfreq[*((const unsigned char *) str[i])].freq;
1413*7304104dSAndroid Build Coastguard Worker 
1414*7304104dSAndroid Build Coastguard Worker   qsort (pfxfreq, 256, sizeof (struct charfreq), compare_freq);
1415*7304104dSAndroid Build Coastguard Worker 
1416*7304104dSAndroid Build Coastguard Worker   size_t n = 0;
1417*7304104dSAndroid Build Coastguard Worker   while (n < 256 && pfxfreq[n].freq != 0)
1418*7304104dSAndroid Build Coastguard Worker     ++n;
1419*7304104dSAndroid Build Coastguard Worker   return n;
1420*7304104dSAndroid Build Coastguard Worker }
1421*7304104dSAndroid Build Coastguard Worker 
1422*7304104dSAndroid Build Coastguard Worker 
1423*7304104dSAndroid Build Coastguard Worker struct strsnlen
1424*7304104dSAndroid Build Coastguard Worker {
1425*7304104dSAndroid Build Coastguard Worker   const char *str;
1426*7304104dSAndroid Build Coastguard Worker   size_t len;
1427*7304104dSAndroid Build Coastguard Worker };
1428*7304104dSAndroid Build Coastguard Worker 
1429*7304104dSAndroid Build Coastguard Worker static size_t
1430*7304104dSAndroid Build Coastguard Worker compute_sfxfreq (size_t nstr, struct strsnlen *strsnlen)
1431*7304104dSAndroid Build Coastguard Worker {
1432*7304104dSAndroid Build Coastguard Worker   memset (sfxfreq, '\0', sizeof (sfxfreq));
1433*7304104dSAndroid Build Coastguard Worker 
1434*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nstr; ++i)
1435*7304104dSAndroid Build Coastguard Worker     sfxfreq[i].ch = i;
1436*7304104dSAndroid Build Coastguard Worker 
1437*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nstr; ++i)
1438*7304104dSAndroid Build Coastguard Worker     ++sfxfreq[((const unsigned char *) strchrnul (strsnlen[i].str, '\0'))[-1]].freq;
1439*7304104dSAndroid Build Coastguard Worker 
1440*7304104dSAndroid Build Coastguard Worker   qsort (sfxfreq, 256, sizeof (struct charfreq), compare_freq);
1441*7304104dSAndroid Build Coastguard Worker 
1442*7304104dSAndroid Build Coastguard Worker   size_t n = 0;
1443*7304104dSAndroid Build Coastguard Worker   while (n < 256 && sfxfreq[n].freq != 0)
1444*7304104dSAndroid Build Coastguard Worker     ++n;
1445*7304104dSAndroid Build Coastguard Worker   return n;
1446*7304104dSAndroid Build Coastguard Worker }
1447*7304104dSAndroid Build Coastguard Worker 
1448*7304104dSAndroid Build Coastguard Worker 
1449*7304104dSAndroid Build Coastguard Worker static void
1450*7304104dSAndroid Build Coastguard Worker create_mnemonic_table (void)
1451*7304104dSAndroid Build Coastguard Worker {
1452*7304104dSAndroid Build Coastguard Worker   mnemonic_strs = xmalloc (nmnemonics * sizeof (char *));
1453*7304104dSAndroid Build Coastguard Worker 
1454*7304104dSAndroid Build Coastguard Worker   twalk (mnemonics, add_mnemonics);
1455*7304104dSAndroid Build Coastguard Worker 
1456*7304104dSAndroid Build Coastguard Worker   (void) which_chars (mnemonic_strs, nmnemonic_strs);
1457*7304104dSAndroid Build Coastguard Worker 
1458*7304104dSAndroid Build Coastguard Worker   size_t best_so_far = 100000000;
1459*7304104dSAndroid Build Coastguard Worker   char *best_prefix = NULL;
1460*7304104dSAndroid Build Coastguard Worker   char *best_suffix = NULL;
1461*7304104dSAndroid Build Coastguard Worker   char *best_table = NULL;
1462*7304104dSAndroid Build Coastguard Worker   size_t best_table_size = 0;
1463*7304104dSAndroid Build Coastguard Worker   size_t best_table_bits = 0;
1464*7304104dSAndroid Build Coastguard Worker   size_t best_prefix_bits = 0;
1465*7304104dSAndroid Build Coastguard Worker 
1466*7304104dSAndroid Build Coastguard Worker   /* We can precompute the prefix characters.  */
1467*7304104dSAndroid Build Coastguard Worker   size_t npfx_char = compute_pfxfreq (mnemonic_strs, nmnemonic_strs);
1468*7304104dSAndroid Build Coastguard Worker 
1469*7304104dSAndroid Build Coastguard Worker   /* Compute best size for string representation including explicit NUL.  */
1470*7304104dSAndroid Build Coastguard Worker   for (size_t pfxbits = 0; (1u << pfxbits) < 2 * npfx_char; ++pfxbits)
1471*7304104dSAndroid Build Coastguard Worker     {
1472*7304104dSAndroid Build Coastguard Worker       char prefix[1 << pfxbits];
1473*7304104dSAndroid Build Coastguard Worker       size_t i;
1474*7304104dSAndroid Build Coastguard Worker       for (i = 0; i < (1u << pfxbits) - 1; ++i)
1475*7304104dSAndroid Build Coastguard Worker 	prefix[i] = pfxfreq[i].ch;
1476*7304104dSAndroid Build Coastguard Worker       prefix[i] = '\0';
1477*7304104dSAndroid Build Coastguard Worker 
1478*7304104dSAndroid Build Coastguard Worker       struct strsnlen strsnlen[nmnemonic_strs];
1479*7304104dSAndroid Build Coastguard Worker 
1480*7304104dSAndroid Build Coastguard Worker       for (i = 0; i < nmnemonic_strs; ++i)
1481*7304104dSAndroid Build Coastguard Worker 	{
1482*7304104dSAndroid Build Coastguard Worker 	  if (strchr (prefix, *mnemonic_strs[i]) != NULL)
1483*7304104dSAndroid Build Coastguard Worker 	    strsnlen[i].str = mnemonic_strs[i] + 1;
1484*7304104dSAndroid Build Coastguard Worker 	  else
1485*7304104dSAndroid Build Coastguard Worker 	    strsnlen[i].str = mnemonic_strs[i];
1486*7304104dSAndroid Build Coastguard Worker 	  strsnlen[i].len = strlen (strsnlen[i].str);
1487*7304104dSAndroid Build Coastguard Worker 	}
1488*7304104dSAndroid Build Coastguard Worker 
1489*7304104dSAndroid Build Coastguard Worker       /* With the prefixes gone, try to combine strings.  */
1490*7304104dSAndroid Build Coastguard Worker       size_t nstrsnlen = 1;
1491*7304104dSAndroid Build Coastguard Worker       for (i = 1; i < nmnemonic_strs; ++i)
1492*7304104dSAndroid Build Coastguard Worker 	{
1493*7304104dSAndroid Build Coastguard Worker 	  size_t j;
1494*7304104dSAndroid Build Coastguard Worker 	  for (j = 0; j < nstrsnlen; ++j)
1495*7304104dSAndroid Build Coastguard Worker 	    if (strsnlen[i].len > strsnlen[j].len
1496*7304104dSAndroid Build Coastguard Worker 		&& strcmp (strsnlen[j].str,
1497*7304104dSAndroid Build Coastguard Worker 			   strsnlen[i].str + (strsnlen[i].len
1498*7304104dSAndroid Build Coastguard Worker 					      - strsnlen[j].len)) == 0)
1499*7304104dSAndroid Build Coastguard Worker 	      {
1500*7304104dSAndroid Build Coastguard Worker 		strsnlen[j] = strsnlen[i];
1501*7304104dSAndroid Build Coastguard Worker 		break;
1502*7304104dSAndroid Build Coastguard Worker 	      }
1503*7304104dSAndroid Build Coastguard Worker 	    else if (strsnlen[i].len < strsnlen[j].len
1504*7304104dSAndroid Build Coastguard Worker 		     && strcmp (strsnlen[i].str,
1505*7304104dSAndroid Build Coastguard Worker 				strsnlen[j].str + (strsnlen[j].len
1506*7304104dSAndroid Build Coastguard Worker 						   - strsnlen[i].len)) == 0)
1507*7304104dSAndroid Build Coastguard Worker 	      break;
1508*7304104dSAndroid Build Coastguard Worker ;
1509*7304104dSAndroid Build Coastguard Worker 	  if (j == nstrsnlen)
1510*7304104dSAndroid Build Coastguard Worker 	      strsnlen[nstrsnlen++] = strsnlen[i];
1511*7304104dSAndroid Build Coastguard Worker 	}
1512*7304104dSAndroid Build Coastguard Worker 
1513*7304104dSAndroid Build Coastguard Worker       size_t nsfx_char = compute_sfxfreq (nstrsnlen, strsnlen);
1514*7304104dSAndroid Build Coastguard Worker 
1515*7304104dSAndroid Build Coastguard Worker       for (size_t sfxbits = 0; (1u << sfxbits) < 2 * nsfx_char; ++sfxbits)
1516*7304104dSAndroid Build Coastguard Worker 	{
1517*7304104dSAndroid Build Coastguard Worker 	  char suffix[1 << sfxbits];
1518*7304104dSAndroid Build Coastguard Worker 
1519*7304104dSAndroid Build Coastguard Worker 	  for (i = 0; i < (1u << sfxbits) - 1; ++i)
1520*7304104dSAndroid Build Coastguard Worker 	    suffix[i] = sfxfreq[i].ch;
1521*7304104dSAndroid Build Coastguard Worker 	  suffix[i] = '\0';
1522*7304104dSAndroid Build Coastguard Worker 
1523*7304104dSAndroid Build Coastguard Worker 	  size_t newlen[nstrsnlen];
1524*7304104dSAndroid Build Coastguard Worker 
1525*7304104dSAndroid Build Coastguard Worker 	  for (i = 0; i < nstrsnlen; ++i)
1526*7304104dSAndroid Build Coastguard Worker 	    if (strchr (suffix, strsnlen[i].str[strsnlen[i].len - 1]) != NULL)
1527*7304104dSAndroid Build Coastguard Worker 	      newlen[i] = strsnlen[i].len - 1;
1528*7304104dSAndroid Build Coastguard Worker 	    else
1529*7304104dSAndroid Build Coastguard Worker 	      newlen[i] = strsnlen[i].len;
1530*7304104dSAndroid Build Coastguard Worker 
1531*7304104dSAndroid Build Coastguard Worker 	  char charused[256];
1532*7304104dSAndroid Build Coastguard Worker 	  memset (charused, '\0', sizeof (charused));
1533*7304104dSAndroid Build Coastguard Worker 	  size_t ncharused = 0;
1534*7304104dSAndroid Build Coastguard Worker 
1535*7304104dSAndroid Build Coastguard Worker 	  const char *tablestr[nstrsnlen];
1536*7304104dSAndroid Build Coastguard Worker 	  size_t ntablestr = 1;
1537*7304104dSAndroid Build Coastguard Worker 	  tablestr[0] = strsnlen[0].str;
1538*7304104dSAndroid Build Coastguard Worker 	  size_t table = newlen[0] + 1;
1539*7304104dSAndroid Build Coastguard Worker 	  for (i = 1; i < nstrsnlen; ++i)
1540*7304104dSAndroid Build Coastguard Worker 	    {
1541*7304104dSAndroid Build Coastguard Worker 	      size_t j;
1542*7304104dSAndroid Build Coastguard Worker 	      for (j = 0; j < ntablestr; ++j)
1543*7304104dSAndroid Build Coastguard Worker 		if (newlen[i] > newlen[j]
1544*7304104dSAndroid Build Coastguard Worker 		    && memcmp (tablestr[j],
1545*7304104dSAndroid Build Coastguard Worker 			       strsnlen[i].str + (newlen[i] - newlen[j]),
1546*7304104dSAndroid Build Coastguard Worker 			       newlen[j]) == 0)
1547*7304104dSAndroid Build Coastguard Worker 		  {
1548*7304104dSAndroid Build Coastguard Worker 		    table += newlen[i] - newlen[j];
1549*7304104dSAndroid Build Coastguard Worker 		    tablestr[j] = strsnlen[i].str;
1550*7304104dSAndroid Build Coastguard Worker 		    newlen[j] = newlen[i];
1551*7304104dSAndroid Build Coastguard Worker 		    break;
1552*7304104dSAndroid Build Coastguard Worker 		  }
1553*7304104dSAndroid Build Coastguard Worker 		else if (newlen[i] < newlen[j]
1554*7304104dSAndroid Build Coastguard Worker 		     && memcmp (strsnlen[i].str,
1555*7304104dSAndroid Build Coastguard Worker 				tablestr[j] + (newlen[j] - newlen[i]),
1556*7304104dSAndroid Build Coastguard Worker 				newlen[i]) == 0)
1557*7304104dSAndroid Build Coastguard Worker 		  break;
1558*7304104dSAndroid Build Coastguard Worker 
1559*7304104dSAndroid Build Coastguard Worker 	      if (j == ntablestr)
1560*7304104dSAndroid Build Coastguard Worker 		{
1561*7304104dSAndroid Build Coastguard Worker 		  table += newlen[i] + 1;
1562*7304104dSAndroid Build Coastguard Worker 		  tablestr[ntablestr] = strsnlen[i].str;
1563*7304104dSAndroid Build Coastguard Worker 		  newlen[ntablestr] = newlen[i];
1564*7304104dSAndroid Build Coastguard Worker 
1565*7304104dSAndroid Build Coastguard Worker 		  ++ntablestr;
1566*7304104dSAndroid Build Coastguard Worker 		}
1567*7304104dSAndroid Build Coastguard Worker 
1568*7304104dSAndroid Build Coastguard Worker 	      for (size_t x = 0; x < newlen[j]; ++x)
1569*7304104dSAndroid Build Coastguard Worker 		if (charused[((const unsigned char *) tablestr[j])[x]]++ == 0)
1570*7304104dSAndroid Build Coastguard Worker 		  ++ncharused;
1571*7304104dSAndroid Build Coastguard Worker 	    }
1572*7304104dSAndroid Build Coastguard Worker 
1573*7304104dSAndroid Build Coastguard Worker 	  size_t ncharused_bits = 0;
1574*7304104dSAndroid Build Coastguard Worker 	  i = 1;
1575*7304104dSAndroid Build Coastguard Worker 	  while (i < ncharused)
1576*7304104dSAndroid Build Coastguard Worker 	    {
1577*7304104dSAndroid Build Coastguard Worker 	      i *= 2;
1578*7304104dSAndroid Build Coastguard Worker 	      ++ncharused_bits;
1579*7304104dSAndroid Build Coastguard Worker 	    }
1580*7304104dSAndroid Build Coastguard Worker 
1581*7304104dSAndroid Build Coastguard Worker 	  size_t table_bits = 0;
1582*7304104dSAndroid Build Coastguard Worker 	  i = 1;
1583*7304104dSAndroid Build Coastguard Worker 	  while (i < table)
1584*7304104dSAndroid Build Coastguard Worker 	    {
1585*7304104dSAndroid Build Coastguard Worker 	      i *= 2;
1586*7304104dSAndroid Build Coastguard Worker 	      ++table_bits;
1587*7304104dSAndroid Build Coastguard Worker 	    }
1588*7304104dSAndroid Build Coastguard Worker 
1589*7304104dSAndroid Build Coastguard Worker 	  size_t mnemonic_bits = table_bits + pfxbits + sfxbits;
1590*7304104dSAndroid Build Coastguard Worker 	  size_t new_total = (((table + 7) / 8) * ncharused_bits + ncharused
1591*7304104dSAndroid Build Coastguard Worker 			      + (pfxbits == 0 ? 0 : (1 << pfxbits) - 1)
1592*7304104dSAndroid Build Coastguard Worker 			      + (sfxbits == 0 ? 0 : (1 << sfxbits) - 1)
1593*7304104dSAndroid Build Coastguard Worker 			      + (((total_bits + mnemonic_bits + 7) / 8)
1594*7304104dSAndroid Build Coastguard Worker 				 * ninstructions));
1595*7304104dSAndroid Build Coastguard Worker 
1596*7304104dSAndroid Build Coastguard Worker 	  if (new_total < best_so_far)
1597*7304104dSAndroid Build Coastguard Worker 	    {
1598*7304104dSAndroid Build Coastguard Worker 	      best_so_far = new_total;
1599*7304104dSAndroid Build Coastguard Worker 	      best_mnemonic_bits = mnemonic_bits;
1600*7304104dSAndroid Build Coastguard Worker 
1601*7304104dSAndroid Build Coastguard Worker 	      free (best_suffix);
1602*7304104dSAndroid Build Coastguard Worker 	      best_suffix = xstrdup (suffix);
1603*7304104dSAndroid Build Coastguard Worker 
1604*7304104dSAndroid Build Coastguard Worker 	      free (best_prefix);
1605*7304104dSAndroid Build Coastguard Worker 	      best_prefix = xstrdup (prefix);
1606*7304104dSAndroid Build Coastguard Worker 	      best_prefix_bits = pfxbits;
1607*7304104dSAndroid Build Coastguard Worker 
1608*7304104dSAndroid Build Coastguard Worker 	      best_table_size = table;
1609*7304104dSAndroid Build Coastguard Worker 	      best_table_bits = table_bits;
1610*7304104dSAndroid Build Coastguard Worker 	      char *cp = best_table = xrealloc (best_table, table);
1611*7304104dSAndroid Build Coastguard Worker 	      for (i = 0; i < ntablestr; ++i)
1612*7304104dSAndroid Build Coastguard Worker 		{
1613*7304104dSAndroid Build Coastguard Worker 		  assert (cp + newlen[i] + 1 <= best_table + table);
1614*7304104dSAndroid Build Coastguard Worker 		  cp = mempcpy (cp, tablestr[i], newlen[i]);
1615*7304104dSAndroid Build Coastguard Worker 		  *cp++ = '\0';
1616*7304104dSAndroid Build Coastguard Worker 		}
1617*7304104dSAndroid Build Coastguard Worker 	      assert (cp == best_table + table);
1618*7304104dSAndroid Build Coastguard Worker 	    }
1619*7304104dSAndroid Build Coastguard Worker 	}
1620*7304104dSAndroid Build Coastguard Worker     }
1621*7304104dSAndroid Build Coastguard Worker 
1622*7304104dSAndroid Build Coastguard Worker   fputs ("static const char mnemonic_table[] =\n\"", outfile);
1623*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < best_table_size; ++i)
1624*7304104dSAndroid Build Coastguard Worker     {
1625*7304104dSAndroid Build Coastguard Worker       if (((i + 1) % 60) == 0)
1626*7304104dSAndroid Build Coastguard Worker 	fputs ("\"\n\"", outfile);
1627*7304104dSAndroid Build Coastguard Worker       if (!isascii (best_table[i]) || !isprint (best_table[i]))
1628*7304104dSAndroid Build Coastguard Worker 	fprintf (outfile, "\\%03o", best_table[i]);
1629*7304104dSAndroid Build Coastguard Worker       else
1630*7304104dSAndroid Build Coastguard Worker 	fputc (best_table[i], outfile);
1631*7304104dSAndroid Build Coastguard Worker     }
1632*7304104dSAndroid Build Coastguard Worker   fputs ("\";\n", outfile);
1633*7304104dSAndroid Build Coastguard Worker 
1634*7304104dSAndroid Build Coastguard Worker   if (best_prefix[0] != '\0')
1635*7304104dSAndroid Build Coastguard Worker     fprintf (outfile,
1636*7304104dSAndroid Build Coastguard Worker 	     "static const char prefix[%zu] = \"%s\";\n"
1637*7304104dSAndroid Build Coastguard Worker 	     "#define PREFIXCHAR_BITS %zu\n",
1638*7304104dSAndroid Build Coastguard Worker 	     strlen (best_prefix), best_prefix, best_prefix_bits);
1639*7304104dSAndroid Build Coastguard Worker   else
1640*7304104dSAndroid Build Coastguard Worker     fputs ("#define NO_PREFIX\n", outfile);
1641*7304104dSAndroid Build Coastguard Worker 
1642*7304104dSAndroid Build Coastguard Worker   if (best_suffix[0] != '\0')
1643*7304104dSAndroid Build Coastguard Worker     fprintf (outfile, "static const char suffix[%zu] = \"%s\";\n",
1644*7304104dSAndroid Build Coastguard Worker 	     strlen (best_suffix), best_suffix);
1645*7304104dSAndroid Build Coastguard Worker   else
1646*7304104dSAndroid Build Coastguard Worker     fputs ("#define NO_SUFFIX\n", outfile);
1647*7304104dSAndroid Build Coastguard Worker 
1648*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nmnemonic_strs; ++i)
1649*7304104dSAndroid Build Coastguard Worker     {
1650*7304104dSAndroid Build Coastguard Worker       const char *mne = mnemonic_strs[i];
1651*7304104dSAndroid Build Coastguard Worker 
1652*7304104dSAndroid Build Coastguard Worker       size_t pfxval = 0;
1653*7304104dSAndroid Build Coastguard Worker       char *cp = strchr (best_prefix, *mne);
1654*7304104dSAndroid Build Coastguard Worker       if (cp != NULL)
1655*7304104dSAndroid Build Coastguard Worker 	{
1656*7304104dSAndroid Build Coastguard Worker 	  pfxval = 1 + (cp - best_prefix);
1657*7304104dSAndroid Build Coastguard Worker 	  ++mne;
1658*7304104dSAndroid Build Coastguard Worker 	}
1659*7304104dSAndroid Build Coastguard Worker 
1660*7304104dSAndroid Build Coastguard Worker       size_t l = strlen (mne);
1661*7304104dSAndroid Build Coastguard Worker 
1662*7304104dSAndroid Build Coastguard Worker       size_t sfxval = 0;
1663*7304104dSAndroid Build Coastguard Worker       cp = strchr (best_suffix, mne[l - 1]);
1664*7304104dSAndroid Build Coastguard Worker       if (cp != NULL)
1665*7304104dSAndroid Build Coastguard Worker 	{
1666*7304104dSAndroid Build Coastguard Worker 	  sfxval = 1 + (cp - best_suffix);
1667*7304104dSAndroid Build Coastguard Worker 	  --l;
1668*7304104dSAndroid Build Coastguard Worker 	}
1669*7304104dSAndroid Build Coastguard Worker 
1670*7304104dSAndroid Build Coastguard Worker       char *off = memmem (best_table, best_table_size, mne, l);
1671*7304104dSAndroid Build Coastguard Worker       while (off[l] != '\0')
1672*7304104dSAndroid Build Coastguard Worker 	{
1673*7304104dSAndroid Build Coastguard Worker 	  off = memmem (off + 1, best_table_size, mne, l);
1674*7304104dSAndroid Build Coastguard Worker 	  assert (off != NULL);
1675*7304104dSAndroid Build Coastguard Worker 	}
1676*7304104dSAndroid Build Coastguard Worker 
1677*7304104dSAndroid Build Coastguard Worker       fprintf (outfile, "#define MNE_%s %#zx\n",
1678*7304104dSAndroid Build Coastguard Worker 	       mnemonic_strs[i],
1679*7304104dSAndroid Build Coastguard Worker 	       (off - best_table)
1680*7304104dSAndroid Build Coastguard Worker 	       + ((pfxval + (sfxval << best_prefix_bits)) << best_table_bits));
1681*7304104dSAndroid Build Coastguard Worker     }
1682*7304104dSAndroid Build Coastguard Worker }
1683*7304104dSAndroid Build Coastguard Worker #endif
1684