xref: /netbsd-src/external/gpl3/binutils/dist/opcodes/i386-gen.c (revision 4e6df137e8e14049b5a701d249962c480449c141)
1 /* Copyright 2007, 2008  Free Software Foundation, Inc.
2 
3    This file is part of the GNU opcodes library.
4 
5    This library is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3, or (at your option)
8    any later version.
9 
10    It is distributed in the hope that it will be useful, but WITHOUT
11    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
13    License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18    MA 02110-1301, USA.  */
19 
20 #include "sysdep.h"
21 #include <stdio.h>
22 #include <errno.h>
23 #include "getopt.h"
24 #include "libiberty.h"
25 #include "safe-ctype.h"
26 
27 #include "i386-opc.h"
28 
29 #include <libintl.h>
30 #define _(String) gettext (String)
31 
32 static const char *program_name = NULL;
33 static int debug = 0;
34 
35 typedef struct initializer
36 {
37   const char *name;
38   const char *init;
39 } initializer;
40 
41 static initializer cpu_flag_init [] =
42 {
43   { "CPU_UNKNOWN_FLAGS",
44     "unknown" },
45   { "CPU_GENERIC32_FLAGS",
46     "Cpu186|Cpu286|Cpu386" },
47   { "CPU_GENERIC64_FLAGS",
48     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuLM" },
49   { "CPU_NONE_FLAGS",
50    "0" },
51   { "CPU_I186_FLAGS",
52     "Cpu186" },
53   { "CPU_I286_FLAGS",
54     "Cpu186|Cpu286" },
55   { "CPU_I386_FLAGS",
56     "Cpu186|Cpu286|Cpu386" },
57   { "CPU_I486_FLAGS",
58     "Cpu186|Cpu286|Cpu386|Cpu486" },
59   { "CPU_I586_FLAGS",
60     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
61   { "CPU_I686_FLAGS",
62     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686" },
63   { "CPU_P2_FLAGS",
64     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX" },
65   { "CPU_P3_FLAGS",
66     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuSSE" },
67   { "CPU_P4_FLAGS",
68     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2" },
69   { "CPU_NOCONA_FLAGS",
70     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
71   { "CPU_CORE_FLAGS",
72     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
73   { "CPU_CORE2_FLAGS",
74     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
75   { "CPU_K6_FLAGS",
76     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX" },
77   { "CPU_K6_2_FLAGS",
78     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow" },
79   { "CPU_ATHLON_FLAGS",
80     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuMMX|Cpu3dnow|Cpu3dnowA" },
81   { "CPU_K8_FLAGS",
82     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
83   { "CPU_AMDFAM10_FLAGS",
84     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
85   { "CPU_MMX_FLAGS",
86     "CpuMMX" },
87   { "CPU_SSE_FLAGS",
88     "CpuMMX|CpuSSE" },
89   { "CPU_SSE2_FLAGS",
90     "CpuMMX|CpuSSE|CpuSSE2" },
91   { "CPU_SSE3_FLAGS",
92     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
93   { "CPU_SSSE3_FLAGS",
94     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
95   { "CPU_SSE4_1_FLAGS",
96     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
97   { "CPU_SSE4_2_FLAGS",
98     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
99   { "CPU_VMX_FLAGS",
100     "CpuVMX" },
101   { "CPU_SMX_FLAGS",
102     "CpuSMX" },
103   { "CPU_XSAVE_FLAGS",
104     "CpuXsave" },
105   { "CPU_AES_FLAGS",
106     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
107   { "CPU_PCLMUL_FLAGS",
108     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
109   { "CPU_FMA_FLAGS",
110     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
111   { "CPU_MOVBE_FLAGS",
112     "CpuMovbe" },
113   { "CPU_EPT_FLAGS",
114     "CpuEPT" },
115   { "CPU_3DNOW_FLAGS",
116     "CpuMMX|Cpu3dnow" },
117   { "CPU_3DNOWA_FLAGS",
118     "CpuMMX|Cpu3dnow|Cpu3dnowA" },
119   { "CPU_PADLOCK_FLAGS",
120     "CpuPadLock" },
121   { "CPU_SVME_FLAGS",
122     "CpuSVME" },
123   { "CPU_SSE4A_FLAGS",
124     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
125   { "CPU_ABM_FLAGS",
126     "CpuABM" },
127   { "CPU_SSE5_FLAGS",
128     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
129   { "CPU_AVX_FLAGS",
130     "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
131 };
132 
133 static initializer operand_type_init [] =
134 {
135   { "OPERAND_TYPE_NONE",
136     "0" },
137   { "OPERAND_TYPE_REG8",
138     "Reg8" },
139   { "OPERAND_TYPE_REG16",
140     "Reg16" },
141   { "OPERAND_TYPE_REG32",
142     "Reg32" },
143   { "OPERAND_TYPE_REG64",
144     "Reg64" },
145   { "OPERAND_TYPE_IMM1",
146     "Imm1" },
147   { "OPERAND_TYPE_IMM8",
148     "Imm8" },
149   { "OPERAND_TYPE_IMM8S",
150     "Imm8S" },
151   { "OPERAND_TYPE_IMM16",
152     "Imm16" },
153   { "OPERAND_TYPE_IMM32",
154     "Imm32" },
155   { "OPERAND_TYPE_IMM32S",
156     "Imm32S" },
157   { "OPERAND_TYPE_IMM64",
158     "Imm64" },
159   { "OPERAND_TYPE_BASEINDEX",
160     "BaseIndex" },
161   { "OPERAND_TYPE_DISP8",
162     "Disp8" },
163   { "OPERAND_TYPE_DISP16",
164     "Disp16" },
165   { "OPERAND_TYPE_DISP32",
166     "Disp32" },
167   { "OPERAND_TYPE_DISP32S",
168     "Disp32S" },
169   { "OPERAND_TYPE_DISP64",
170     "Disp64" },
171   { "OPERAND_TYPE_INOUTPORTREG",
172     "InOutPortReg" },
173   { "OPERAND_TYPE_SHIFTCOUNT",
174     "ShiftCount" },
175   { "OPERAND_TYPE_CONTROL",
176     "Control" },
177   { "OPERAND_TYPE_TEST",
178     "Test" },
179   { "OPERAND_TYPE_DEBUG",
180     "FloatReg" },
181   { "OPERAND_TYPE_FLOATREG",
182     "FloatReg" },
183   { "OPERAND_TYPE_FLOATACC",
184     "FloatAcc" },
185   { "OPERAND_TYPE_SREG2",
186     "SReg2" },
187   { "OPERAND_TYPE_SREG3",
188     "SReg3" },
189   { "OPERAND_TYPE_ACC",
190     "Acc" },
191   { "OPERAND_TYPE_JUMPABSOLUTE",
192     "JumpAbsolute" },
193   { "OPERAND_TYPE_REGMMX",
194     "RegMMX" },
195   { "OPERAND_TYPE_REGXMM",
196     "RegXMM" },
197   { "OPERAND_TYPE_REGYMM",
198     "RegYMM" },
199   { "OPERAND_TYPE_ESSEG",
200     "EsSeg" },
201   { "OPERAND_TYPE_ACC32",
202     "Reg32|Acc|Dword" },
203   { "OPERAND_TYPE_ACC64",
204     "Reg64|Acc|Qword" },
205   { "OPERAND_TYPE_INOUTPORTREG",
206     "InOutPortReg" },
207   { "OPERAND_TYPE_REG16_INOUTPORTREG",
208     "Reg16|InOutPortReg" },
209   { "OPERAND_TYPE_DISP16_32",
210     "Disp16|Disp32" },
211   { "OPERAND_TYPE_ANYDISP",
212     "Disp8|Disp16|Disp32|Disp32S|Disp64" },
213   { "OPERAND_TYPE_IMM16_32",
214     "Imm16|Imm32" },
215   { "OPERAND_TYPE_IMM16_32S",
216     "Imm16|Imm32S" },
217   { "OPERAND_TYPE_IMM16_32_32S",
218     "Imm16|Imm32|Imm32S" },
219   { "OPERAND_TYPE_IMM32_32S_DISP32",
220     "Imm32|Imm32S|Disp32" },
221   { "OPERAND_TYPE_IMM64_DISP64",
222     "Imm64|Disp64" },
223   { "OPERAND_TYPE_IMM32_32S_64_DISP32",
224     "Imm32|Imm32S|Imm64|Disp32" },
225   { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
226     "Imm32|Imm32S|Imm64|Disp32|Disp64" },
227   { "OPERAND_TYPE_VEX_IMM4",
228     "VEX_Imm4" },
229 };
230 
231 typedef struct bitfield
232 {
233   int position;
234   int value;
235   const char *name;
236 } bitfield;
237 
238 #define BITFIELD(n) { n, 0, #n }
239 
240 static bitfield cpu_flags[] =
241 {
242   BITFIELD (Cpu186),
243   BITFIELD (Cpu286),
244   BITFIELD (Cpu386),
245   BITFIELD (Cpu486),
246   BITFIELD (Cpu586),
247   BITFIELD (Cpu686),
248   BITFIELD (CpuP4),
249   BITFIELD (CpuK6),
250   BITFIELD (CpuK8),
251   BITFIELD (CpuMMX),
252   BITFIELD (CpuSSE),
253   BITFIELD (CpuSSE2),
254   BITFIELD (CpuSSE3),
255   BITFIELD (CpuSSSE3),
256   BITFIELD (CpuSSE4_1),
257   BITFIELD (CpuSSE4_2),
258   BITFIELD (CpuAVX),
259   BITFIELD (CpuSSE4a),
260   BITFIELD (CpuSSE5),
261   BITFIELD (Cpu3dnow),
262   BITFIELD (Cpu3dnowA),
263   BITFIELD (CpuPadLock),
264   BITFIELD (CpuSVME),
265   BITFIELD (CpuVMX),
266   BITFIELD (CpuSMX),
267   BITFIELD (CpuABM),
268   BITFIELD (CpuXsave),
269   BITFIELD (CpuAES),
270   BITFIELD (CpuPCLMUL),
271   BITFIELD (CpuFMA),
272   BITFIELD (CpuLM),
273   BITFIELD (CpuMovbe),
274   BITFIELD (CpuEPT),
275   BITFIELD (Cpu64),
276   BITFIELD (CpuNo64),
277 #ifdef CpuUnused
278   BITFIELD (CpuUnused),
279 #endif
280 };
281 
282 static bitfield opcode_modifiers[] =
283 {
284   BITFIELD (D),
285   BITFIELD (W),
286   BITFIELD (Modrm),
287   BITFIELD (ShortForm),
288   BITFIELD (Jump),
289   BITFIELD (JumpDword),
290   BITFIELD (JumpByte),
291   BITFIELD (JumpInterSegment),
292   BITFIELD (FloatMF),
293   BITFIELD (FloatR),
294   BITFIELD (FloatD),
295   BITFIELD (Size16),
296   BITFIELD (Size32),
297   BITFIELD (Size64),
298   BITFIELD (IgnoreSize),
299   BITFIELD (DefaultSize),
300   BITFIELD (No_bSuf),
301   BITFIELD (No_wSuf),
302   BITFIELD (No_lSuf),
303   BITFIELD (No_sSuf),
304   BITFIELD (No_qSuf),
305   BITFIELD (No_ldSuf),
306   BITFIELD (FWait),
307   BITFIELD (IsString),
308   BITFIELD (RegKludge),
309   BITFIELD (FirstXmm0),
310   BITFIELD (Implicit1stXmm0),
311   BITFIELD (ByteOkIntel),
312   BITFIELD (ToDword),
313   BITFIELD (ToQword),
314   BITFIELD (AddrPrefixOp0),
315   BITFIELD (IsPrefix),
316   BITFIELD (ImmExt),
317   BITFIELD (NoRex64),
318   BITFIELD (Rex64),
319   BITFIELD (Ugh),
320   BITFIELD (Drex),
321   BITFIELD (Drexv),
322   BITFIELD (Drexc),
323   BITFIELD (Vex),
324   BITFIELD (Vex256),
325   BITFIELD (VexNDD),
326   BITFIELD (VexNDS),
327   BITFIELD (VexW0),
328   BITFIELD (VexW1),
329   BITFIELD (Vex0F),
330   BITFIELD (Vex0F38),
331   BITFIELD (Vex0F3A),
332   BITFIELD (Vex3Sources),
333   BITFIELD (VexImmExt),
334   BITFIELD (SSE2AVX),
335   BITFIELD (NoAVX),
336   BITFIELD (OldGcc),
337   BITFIELD (ATTMnemonic),
338   BITFIELD (ATTSyntax),
339   BITFIELD (IntelSyntax),
340 };
341 
342 static bitfield operand_types[] =
343 {
344   BITFIELD (Reg8),
345   BITFIELD (Reg16),
346   BITFIELD (Reg32),
347   BITFIELD (Reg64),
348   BITFIELD (FloatReg),
349   BITFIELD (RegMMX),
350   BITFIELD (RegXMM),
351   BITFIELD (RegYMM),
352   BITFIELD (Imm8),
353   BITFIELD (Imm8S),
354   BITFIELD (Imm16),
355   BITFIELD (Imm32),
356   BITFIELD (Imm32S),
357   BITFIELD (Imm64),
358   BITFIELD (Imm1),
359   BITFIELD (BaseIndex),
360   BITFIELD (Disp8),
361   BITFIELD (Disp16),
362   BITFIELD (Disp32),
363   BITFIELD (Disp32S),
364   BITFIELD (Disp64),
365   BITFIELD (InOutPortReg),
366   BITFIELD (ShiftCount),
367   BITFIELD (Control),
368   BITFIELD (Debug),
369   BITFIELD (Test),
370   BITFIELD (SReg2),
371   BITFIELD (SReg3),
372   BITFIELD (Acc),
373   BITFIELD (FloatAcc),
374   BITFIELD (JumpAbsolute),
375   BITFIELD (EsSeg),
376   BITFIELD (RegMem),
377   BITFIELD (Mem),
378   BITFIELD (Byte),
379   BITFIELD (Word),
380   BITFIELD (Dword),
381   BITFIELD (Fword),
382   BITFIELD (Qword),
383   BITFIELD (Tbyte),
384   BITFIELD (Xmmword),
385   BITFIELD (Ymmword),
386   BITFIELD (Unspecified),
387   BITFIELD (Anysize),
388   BITFIELD (Vex_Imm4),
389 #ifdef OTUnused
390   BITFIELD (OTUnused),
391 #endif
392 };
393 
394 static int lineno;
395 static const char *filename;
396 
397 static int
398 compare (const void *x, const void *y)
399 {
400   const bitfield *xp = (const bitfield *) x;
401   const bitfield *yp = (const bitfield *) y;
402   return xp->position - yp->position;
403 }
404 
405 static void
406 fail (const char *message, ...)
407 {
408   va_list args;
409 
410   va_start (args, message);
411   fprintf (stderr, _("%s: Error: "), program_name);
412   vfprintf (stderr, message, args);
413   va_end (args);
414   xexit (1);
415 }
416 
417 static void
418 process_copyright (FILE *fp)
419 {
420   fprintf (fp, "/* This file is automatically generated by i386-gen.  Do not edit!  */\n\
421 /* Copyright 2007, 2008  Free Software Foundation, Inc.\n\
422 \n\
423    This file is part of the GNU opcodes library.\n\
424 \n\
425    This library is free software; you can redistribute it and/or modify\n\
426    it under the terms of the GNU General Public License as published by\n\
427    the Free Software Foundation; either version 3, or (at your option)\n\
428    any later version.\n\
429 \n\
430    It is distributed in the hope that it will be useful, but WITHOUT\n\
431    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
432    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\n\
433    License for more details.\n\
434 \n\
435    You should have received a copy of the GNU General Public License\n\
436    along with this program; if not, write to the Free Software\n\
437    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
438    MA 02110-1301, USA.  */\n");
439 }
440 
441 /* Remove leading white spaces.  */
442 
443 static char *
444 remove_leading_whitespaces (char *str)
445 {
446   while (ISSPACE (*str))
447     str++;
448   return str;
449 }
450 
451 /* Remove trailing white spaces.  */
452 
453 static void
454 remove_trailing_whitespaces (char *str)
455 {
456   size_t last = strlen (str);
457 
458   if (last == 0)
459     return;
460 
461   do
462     {
463       last--;
464       if (ISSPACE (str [last]))
465 	str[last] = '\0';
466       else
467 	break;
468     }
469   while (last != 0);
470 }
471 
472 /* Find next field separated by SEP and terminate it. Return a
473    pointer to the one after it.  */
474 
475 static char *
476 next_field (char *str, char sep, char **next)
477 {
478   char *p;
479 
480   p = remove_leading_whitespaces (str);
481   for (str = p; *str != sep && *str != '\0'; str++);
482 
483   *str = '\0';
484   remove_trailing_whitespaces (p);
485 
486   *next = str + 1;
487 
488   return p;
489 }
490 
491 static void
492 set_bitfield (const char *f, bitfield *array, unsigned int size)
493 {
494   unsigned int i;
495 
496   if (strcmp (f, "CpuSledgehammer") == 0)
497     f= "CpuK8";
498   else if (strcmp (f, "Mmword") == 0)
499     f= "Qword";
500   else if (strcmp (f, "Oword") == 0)
501     f= "Xmmword";
502 
503   for (i = 0; i < size; i++)
504     if (strcasecmp (array[i].name, f) == 0)
505       {
506 	array[i].value = 1;
507 	return;
508       }
509 
510   fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
511 }
512 
513 static void
514 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
515 		  int macro, const char *comma, const char *indent)
516 {
517   unsigned int i;
518 
519   fprintf (table, "%s{ { ", indent);
520 
521   for (i = 0; i < size - 1; i++)
522     {
523       fprintf (table, "%d, ", flags[i].value);
524       if (((i + 1) % 20) == 0)
525 	{
526 	  /* We need \\ for macro.  */
527 	  if (macro)
528 	    fprintf (table, " \\\n    %s", indent);
529 	  else
530 	    fprintf (table, "\n    %s", indent);
531 	}
532     }
533 
534   fprintf (table, "%d } }%s\n", flags[i].value, comma);
535 }
536 
537 static void
538 process_i386_cpu_flag (FILE *table, char *flag, int macro,
539 		       const char *comma, const char *indent)
540 {
541   char *str, *next, *last;
542   bitfield flags [ARRAY_SIZE (cpu_flags)];
543 
544   /* Copy the default cpu flags.  */
545   memcpy (flags, cpu_flags, sizeof (cpu_flags));
546 
547   if (strcasecmp (flag, "unknown") == 0)
548     {
549       unsigned int i;
550 
551       /* We turn on everything except for cpu64 in case of
552 	 CPU_UNKNOWN_FLAGS. */
553       for (i = 0; i < ARRAY_SIZE (flags); i++)
554 	if (flags[i].position != Cpu64)
555 	  flags[i].value = 1;
556     }
557   else if (strcmp (flag, "0"))
558     {
559       last = flag + strlen (flag);
560       for (next = flag; next && next < last; )
561 	{
562 	  str = next_field (next, '|', &next);
563 	  if (str)
564 	    set_bitfield (str, flags, ARRAY_SIZE (flags));
565 	}
566     }
567 
568   output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
569 		    comma, indent);
570 }
571 
572 static void
573 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
574 {
575   unsigned int i;
576 
577   fprintf (table, "    { ");
578 
579   for (i = 0; i < size - 1; i++)
580     {
581       fprintf (table, "%d, ", modifier[i].value);
582       if (((i + 1) % 20) == 0)
583 	fprintf (table, "\n      ");
584     }
585 
586   fprintf (table, "%d },\n", modifier[i].value);
587 }
588 
589 static void
590 process_i386_opcode_modifier (FILE *table, char *mod)
591 {
592   char *str, *next, *last;
593   bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
594 
595   /* Copy the default opcode modifier.  */
596   memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
597 
598   if (strcmp (mod, "0"))
599     {
600       last = mod + strlen (mod);
601       for (next = mod; next && next < last; )
602 	{
603 	  str = next_field (next, '|', &next);
604 	  if (str)
605 	    set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
606 	}
607     }
608   output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
609 }
610 
611 static void
612 output_operand_type (FILE *table, bitfield *types, unsigned int size,
613 		     int macro, const char *indent)
614 {
615   unsigned int i;
616 
617   fprintf (table, "{ { ");
618 
619   for (i = 0; i < size - 1; i++)
620     {
621       fprintf (table, "%d, ", types[i].value);
622       if (((i + 1) % 20) == 0)
623 	{
624 	  /* We need \\ for macro.  */
625 	  if (macro)
626 	    fprintf (table, "\\\n%s", indent);
627 	  else
628 	    fprintf (table, "\n%s", indent);
629 	}
630     }
631 
632   fprintf (table, "%d } }", types[i].value);
633 }
634 
635 static void
636 process_i386_operand_type (FILE *table, char *op, int macro,
637 			   const char *indent)
638 {
639   char *str, *next, *last;
640   bitfield types [ARRAY_SIZE (operand_types)];
641 
642   /* Copy the default operand type.  */
643   memcpy (types, operand_types, sizeof (types));
644 
645   if (strcmp (op, "0"))
646     {
647       last = op + strlen (op);
648       for (next = op; next && next < last; )
649 	{
650 	  str = next_field (next, '|', &next);
651 	  if (str)
652 	    set_bitfield (str, types, ARRAY_SIZE (types));
653 	}
654     }
655   output_operand_type (table, types, ARRAY_SIZE (types), macro,
656 		       indent);
657 }
658 
659 static void
660 process_i386_opcodes (FILE *table)
661 {
662   FILE *fp;
663   char buf[2048];
664   unsigned int i;
665   char *str, *p, *last;
666   char *name, *operands, *base_opcode, *extension_opcode;
667   char *opcode_length;
668   char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
669 
670   filename = "i386-opc.tbl";
671   fp = fopen (filename, "r");
672 
673   if (fp == NULL)
674     fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
675 	  xstrerror (errno));
676 
677   fprintf (table, "\n/* i386 opcode table.  */\n\n");
678   fprintf (table, "const template i386_optab[] =\n{\n");
679 
680   while (!feof (fp))
681     {
682       if (fgets (buf, sizeof (buf), fp) == NULL)
683 	break;
684 
685       lineno++;
686 
687       p = remove_leading_whitespaces (buf);
688 
689       /* Skip comments.  */
690       str = strstr (p, "//");
691       if (str != NULL)
692 	str[0] = '\0';
693 
694       /* Remove trailing white spaces.  */
695       remove_trailing_whitespaces (p);
696 
697       switch (p[0])
698 	{
699 	case '#':
700 	  fprintf (table, "%s\n", p);
701 	case '\0':
702 	  continue;
703 	  break;
704 	default:
705 	  break;
706 	}
707 
708       last = p + strlen (p);
709 
710       /* Find name.  */
711       name = next_field (p, ',', &str);
712 
713       if (str >= last)
714 	abort ();
715 
716       /* Find number of operands.  */
717       operands = next_field (str, ',', &str);
718 
719       if (str >= last)
720 	abort ();
721 
722       /* Find base_opcode.  */
723       base_opcode = next_field (str, ',', &str);
724 
725       if (str >= last)
726 	abort ();
727 
728       /* Find extension_opcode.  */
729       extension_opcode = next_field (str, ',', &str);
730 
731       if (str >= last)
732 	abort ();
733 
734       /* Find opcode_length.  */
735       opcode_length = next_field (str, ',', &str);
736 
737       if (str >= last)
738 	abort ();
739 
740       /* Find cpu_flags.  */
741       cpu_flags = next_field (str, ',', &str);
742 
743       if (str >= last)
744 	abort ();
745 
746       /* Find opcode_modifier.  */
747       opcode_modifier = next_field (str, ',', &str);
748 
749       if (str >= last)
750 	abort ();
751 
752       /* Remove the first {.  */
753       str = remove_leading_whitespaces (str);
754       if (*str != '{')
755 	abort ();
756       str = remove_leading_whitespaces (str + 1);
757 
758       i = strlen (str);
759 
760       /* There are at least "X}".  */
761       if (i < 2)
762 	abort ();
763 
764       /* Remove trailing white spaces and }. */
765       do
766 	{
767 	  i--;
768 	  if (ISSPACE (str[i]) || str[i] == '}')
769 	    str[i] = '\0';
770 	  else
771 	    break;
772 	}
773       while (i != 0);
774 
775       last = str + i;
776 
777       /* Find operand_types.  */
778       for (i = 0; i < ARRAY_SIZE (operand_types); i++)
779 	{
780 	  if (str >= last)
781 	    {
782 	      operand_types [i] = NULL;
783 	      break;
784 	    }
785 
786 	  operand_types [i] = next_field (str, ',', &str);
787 	  if (*operand_types[i] == '0')
788 	    {
789 	      if (i != 0)
790 		operand_types[i] = NULL;
791 	      break;
792 	    }
793 	}
794 
795       fprintf (table, "  { \"%s\", %s, %s, %s, %s,\n",
796 	       name, operands, base_opcode, extension_opcode,
797 	       opcode_length);
798 
799       process_i386_cpu_flag (table, cpu_flags, 0, ",", "    ");
800 
801       process_i386_opcode_modifier (table, opcode_modifier);
802 
803       fprintf (table, "    { ");
804 
805       for (i = 0; i < ARRAY_SIZE (operand_types); i++)
806 	{
807 	  if (operand_types[i] == NULL
808 	      || *operand_types[i] == '0')
809 	    {
810 	      if (i == 0)
811 		process_i386_operand_type (table, "0", 0, "\t  ");
812 	      break;
813 	    }
814 
815 	  if (i != 0)
816 	    fprintf (table, ",\n      ");
817 
818 	  process_i386_operand_type (table, operand_types[i], 0,
819 				     "\t  ");
820 	}
821       fprintf (table, " } },\n");
822     }
823 
824   fclose (fp);
825 
826   fprintf (table, "  { NULL, 0, 0, 0, 0,\n");
827 
828   process_i386_cpu_flag (table, "0", 0, ",", "    ");
829 
830   process_i386_opcode_modifier (table, "0");
831 
832   fprintf (table, "    { ");
833   process_i386_operand_type (table, "0", 0, "\t  ");
834   fprintf (table, " } }\n");
835 
836   fprintf (table, "};\n");
837 }
838 
839 static void
840 process_i386_registers (FILE *table)
841 {
842   FILE *fp;
843   char buf[2048];
844   char *str, *p, *last;
845   char *reg_name, *reg_type, *reg_flags, *reg_num;
846   char *dw2_32_num, *dw2_64_num;
847 
848   filename = "i386-reg.tbl";
849   fp = fopen (filename, "r");
850   if (fp == NULL)
851     fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
852 	  xstrerror (errno));
853 
854   fprintf (table, "\n/* i386 register table.  */\n\n");
855   fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
856 
857   while (!feof (fp))
858     {
859       if (fgets (buf, sizeof (buf), fp) == NULL)
860 	break;
861 
862       lineno++;
863 
864       p = remove_leading_whitespaces (buf);
865 
866       /* Skip comments.  */
867       str = strstr (p, "//");
868       if (str != NULL)
869 	str[0] = '\0';
870 
871       /* Remove trailing white spaces.  */
872       remove_trailing_whitespaces (p);
873 
874       switch (p[0])
875 	{
876 	case '#':
877 	  fprintf (table, "%s\n", p);
878 	case '\0':
879 	  continue;
880 	  break;
881 	default:
882 	  break;
883 	}
884 
885       last = p + strlen (p);
886 
887       /* Find reg_name.  */
888       reg_name = next_field (p, ',', &str);
889 
890       if (str >= last)
891 	abort ();
892 
893       /* Find reg_type.  */
894       reg_type = next_field (str, ',', &str);
895 
896       if (str >= last)
897 	abort ();
898 
899       /* Find reg_flags.  */
900       reg_flags = next_field (str, ',', &str);
901 
902       if (str >= last)
903 	abort ();
904 
905       /* Find reg_num.  */
906       reg_num = next_field (str, ',', &str);
907 
908       if (str >= last)
909 	abort ();
910 
911       fprintf (table, "  { \"%s\",\n    ", reg_name);
912 
913       process_i386_operand_type (table, reg_type, 0, "\t");
914 
915       /* Find 32-bit Dwarf2 register number.  */
916       dw2_32_num = next_field (str, ',', &str);
917 
918       if (str >= last)
919 	abort ();
920 
921       /* Find 64-bit Dwarf2 register number.  */
922       dw2_64_num = next_field (str, ',', &str);
923 
924       fprintf (table, ",\n    %s, %s, { %s, %s } },\n",
925 	       reg_flags, reg_num, dw2_32_num, dw2_64_num);
926     }
927 
928   fclose (fp);
929 
930   fprintf (table, "};\n");
931 
932   fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
933 }
934 
935 static void
936 process_i386_initializers (void)
937 {
938   unsigned int i;
939   FILE *fp = fopen ("i386-init.h", "w");
940   char *init;
941 
942   if (fp == NULL)
943     fail (_("can't create i386-init.h, errno = %s\n"),
944 	  xstrerror (errno));
945 
946   process_copyright (fp);
947 
948   for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
949     {
950       fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
951       init = xstrdup (cpu_flag_init[i].init);
952       process_i386_cpu_flag (fp, init, 1, "", "  ");
953       free (init);
954     }
955 
956   for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
957     {
958       fprintf (fp, "\n\n#define %s \\\n  ", operand_type_init[i].name);
959       init = xstrdup (operand_type_init[i].init);
960       process_i386_operand_type (fp, init, 1, "      ");
961       free (init);
962     }
963   fprintf (fp, "\n");
964 
965   fclose (fp);
966 }
967 
968 /* Program options.  */
969 #define OPTION_SRCDIR	200
970 
971 struct option long_options[] =
972 {
973   {"srcdir",  required_argument, NULL, OPTION_SRCDIR},
974   {"debug",   no_argument,       NULL, 'd'},
975   {"version", no_argument,       NULL, 'V'},
976   {"help",    no_argument,       NULL, 'h'},
977   {0,         no_argument,       NULL, 0}
978 };
979 
980 static void
981 print_version (void)
982 {
983   printf ("%s: version 1.0\n", program_name);
984   xexit (0);
985 }
986 
987 static void
988 usage (FILE * stream, int status)
989 {
990   fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
991 	   program_name);
992   xexit (status);
993 }
994 
995 int
996 main (int argc, char **argv)
997 {
998   extern int chdir (char *);
999   char *srcdir = NULL;
1000   int c;
1001   FILE *table;
1002 
1003   program_name = *argv;
1004   xmalloc_set_program_name (program_name);
1005 
1006   while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1007     switch (c)
1008       {
1009       case OPTION_SRCDIR:
1010 	srcdir = optarg;
1011 	break;
1012       case 'V':
1013       case 'v':
1014 	print_version ();
1015 	break;
1016       case 'd':
1017 	debug = 1;
1018 	break;
1019       case 'h':
1020       case '?':
1021 	usage (stderr, 0);
1022       default:
1023       case 0:
1024 	break;
1025       }
1026 
1027   if (optind != argc)
1028     usage (stdout, 1);
1029 
1030   if (srcdir != NULL)
1031     if (chdir (srcdir) != 0)
1032       fail (_("unable to change directory to \"%s\", errno = %s\n"),
1033 	    srcdir, xstrerror (errno));
1034 
1035   /* Check the unused bitfield in i386_cpu_flags.  */
1036 #ifndef CpuUnused
1037   c = CpuNumOfBits - CpuMax - 1;
1038   if (c)
1039     fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1040 #endif
1041 
1042   /* Check the unused bitfield in i386_operand_type.  */
1043 #ifndef OTUnused
1044   c = OTNumOfBits - OTMax - 1;
1045   if (c)
1046     fail (_("%d unused bits in i386_operand_type.\n"), c);
1047 #endif
1048 
1049   qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1050 	 compare);
1051 
1052   qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1053 	 sizeof (opcode_modifiers [0]), compare);
1054 
1055   qsort (operand_types, ARRAY_SIZE (operand_types),
1056 	 sizeof (operand_types [0]), compare);
1057 
1058   table = fopen ("i386-tbl.h", "w");
1059   if (table == NULL)
1060     fail (_("can't create i386-tbl.h, errno = %s\n"),
1061 	  xstrerror (errno));
1062 
1063   process_copyright (table);
1064 
1065   process_i386_opcodes (table);
1066   process_i386_registers (table);
1067   process_i386_initializers ();
1068 
1069   fclose (table);
1070 
1071   exit (0);
1072 }
1073