OSDN Git Service

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