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