1 /* Copyright 2007, 2008, 2009, 2010, 2011, 2012
2 Free Software Foundation, Inc.
4 This file is part of the GNU opcodes library.
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
25 #include "libiberty.h"
27 #include "safe-ctype.h"
32 #define _(String) gettext (String)
34 static const char *program_name = NULL;
37 typedef struct initializer
43 static initializer cpu_flag_init[] =
45 { "CPU_UNKNOWN_FLAGS",
46 "~(CpuL1OM|CpuK1OM)" },
47 { "CPU_GENERIC32_FLAGS",
48 "Cpu186|Cpu286|Cpu386" },
49 { "CPU_GENERIC64_FLAGS",
50 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuLM" },
58 "Cpu186|Cpu286|Cpu386" },
60 "Cpu186|Cpu286|Cpu386|Cpu486" },
62 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu387" },
64 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687" },
65 { "CPU_PENTIUMPRO_FLAGS",
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop" },
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX" },
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE" },
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2" },
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM|CpuCX16" },
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuCX16" },
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM|CpuCX16" },
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuRdtscp|CpuLM|CpuCX16" },
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX" },
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuNop|CpuMMX|Cpu3dnow" },
86 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA" },
88 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
89 { "CPU_AMDFAM10_FLAGS",
90 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
92 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA4|CpuXOP|CpuLWP|CpuCX16|CpuClflush|CpuSSSE3|CpuSVME|CpuSSE4_1|CpuSSE4_2|CpuXsave|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW" },
94 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA|CpuFMA4|CpuXOP|CpuLWP|CpuBMI|CpuTBM|CpuF16C|CpuCX16|CpuClflush|CpuSSSE3|CpuSVME|CpuSSE4_1|CpuSSE4_2|CpuXsave|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW" },
96 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA|CpuFMA4|CpuXOP|CpuLWP|CpuBMI|CpuTBM|CpuF16C|CpuCX16|CpuClflush|CpuSSSE3|CpuSVME|CpuSSE4_1|CpuSSE4_2|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW|CpuXsave|CpuXsaveopt" },
98 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4a|CpuABM|CpuLM|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME|CpuLZCNT" },
100 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4a|CpuSSE4_1|CpuSSE4_2|CpuABM|CpuLM|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuAVX|CpuMovbe|CpuXsave|CpuXsaveopt|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME|CpuLZCNT" },
108 "Cpu8087|Cpu287|Cpu387|Cpu687|CpuFISTTP" },
109 { "CPU_CLFLUSH_FLAGS",
113 { "CPU_SYSCALL_FLAGS",
120 "CpuMMX|CpuSSE|CpuSSE2" },
122 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
124 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
125 { "CPU_SSE4_1_FLAGS",
126 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
127 { "CPU_SSE4_2_FLAGS",
128 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
129 { "CPU_ANY_SSE_FLAGS",
130 "CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuAVX|CpuAVX2" },
137 { "CPU_XSAVEOPT_FLAGS",
140 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
141 { "CPU_PCLMUL_FLAGS",
142 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
144 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
146 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA4" },
148 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP" },
159 { "CPU_RDTSCP_FLAGS",
163 { "CPU_FSGSBASE_FLAGS",
177 { "CPU_INVPCID_FLAGS",
179 { "CPU_VMFUNC_FLAGS",
183 { "CPU_3DNOWA_FLAGS",
184 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
185 { "CPU_PADLOCK_FLAGS",
190 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
194 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
196 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2" },
197 { "CPU_ANY_AVX_FLAGS",
205 { "CPU_RDSEED_FLAGS",
207 { "CPU_PRFCHW_FLAGS",
211 static initializer operand_type_init[] =
213 { "OPERAND_TYPE_NONE",
215 { "OPERAND_TYPE_REG8",
217 { "OPERAND_TYPE_REG16",
219 { "OPERAND_TYPE_REG32",
221 { "OPERAND_TYPE_REG64",
223 { "OPERAND_TYPE_IMM1",
225 { "OPERAND_TYPE_IMM8",
227 { "OPERAND_TYPE_IMM8S",
229 { "OPERAND_TYPE_IMM16",
231 { "OPERAND_TYPE_IMM32",
233 { "OPERAND_TYPE_IMM32S",
235 { "OPERAND_TYPE_IMM64",
237 { "OPERAND_TYPE_BASEINDEX",
239 { "OPERAND_TYPE_DISP8",
241 { "OPERAND_TYPE_DISP16",
243 { "OPERAND_TYPE_DISP32",
245 { "OPERAND_TYPE_DISP32S",
247 { "OPERAND_TYPE_DISP64",
249 { "OPERAND_TYPE_INOUTPORTREG",
251 { "OPERAND_TYPE_SHIFTCOUNT",
253 { "OPERAND_TYPE_CONTROL",
255 { "OPERAND_TYPE_TEST",
257 { "OPERAND_TYPE_DEBUG",
259 { "OPERAND_TYPE_FLOATREG",
261 { "OPERAND_TYPE_FLOATACC",
263 { "OPERAND_TYPE_SREG2",
265 { "OPERAND_TYPE_SREG3",
267 { "OPERAND_TYPE_ACC",
269 { "OPERAND_TYPE_JUMPABSOLUTE",
271 { "OPERAND_TYPE_REGMMX",
273 { "OPERAND_TYPE_REGXMM",
275 { "OPERAND_TYPE_REGYMM",
277 { "OPERAND_TYPE_ESSEG",
279 { "OPERAND_TYPE_ACC32",
281 { "OPERAND_TYPE_ACC64",
283 { "OPERAND_TYPE_INOUTPORTREG",
285 { "OPERAND_TYPE_REG16_INOUTPORTREG",
286 "Reg16|InOutPortReg" },
287 { "OPERAND_TYPE_DISP16_32",
289 { "OPERAND_TYPE_ANYDISP",
290 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
291 { "OPERAND_TYPE_IMM16_32",
293 { "OPERAND_TYPE_IMM16_32S",
295 { "OPERAND_TYPE_IMM16_32_32S",
296 "Imm16|Imm32|Imm32S" },
297 { "OPERAND_TYPE_IMM32_32S_DISP32",
298 "Imm32|Imm32S|Disp32" },
299 { "OPERAND_TYPE_IMM64_DISP64",
301 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
302 "Imm32|Imm32S|Imm64|Disp32" },
303 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
304 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
305 { "OPERAND_TYPE_VEC_IMM4",
309 typedef struct bitfield
316 #define BITFIELD(n) { n, 0, #n }
318 static bitfield cpu_flags[] =
326 BITFIELD (CpuClflush),
328 BITFIELD (CpuSYSCALL),
333 BITFIELD (CpuFISTTP),
339 BITFIELD (CpuSSE4_1),
340 BITFIELD (CpuSSE4_2),
347 BITFIELD (Cpu3dnowA),
348 BITFIELD (CpuPadLock),
354 BITFIELD (CpuXsaveopt),
356 BITFIELD (CpuPCLMUL),
367 BITFIELD (CpuRdtscp),
368 BITFIELD (CpuFSGSBase),
375 BITFIELD (CpuINVPCID),
376 BITFIELD (CpuVMFUNC),
377 BITFIELD (CpuRDSEED),
379 BITFIELD (CpuPRFCHW),
383 BITFIELD (CpuUnused),
387 static bitfield opcode_modifiers[] =
393 BITFIELD (ShortForm),
395 BITFIELD (JumpDword),
397 BITFIELD (JumpInterSegment),
404 BITFIELD (CheckRegSize),
405 BITFIELD (IgnoreSize),
406 BITFIELD (DefaultSize),
415 BITFIELD (IsLockable),
416 BITFIELD (RegKludge),
417 BITFIELD (FirstXmm0),
418 BITFIELD (Implicit1stXmm0),
419 BITFIELD (RepPrefixOk),
420 BITFIELD (HLEPrefixOk),
423 BITFIELD (AddrPrefixOp0),
432 BITFIELD (VexOpcode),
433 BITFIELD (VexSources),
434 BITFIELD (VexImmExt),
439 BITFIELD (ATTMnemonic),
440 BITFIELD (ATTSyntax),
441 BITFIELD (IntelSyntax),
444 static bitfield operand_types[] =
461 BITFIELD (BaseIndex),
467 BITFIELD (InOutPortReg),
468 BITFIELD (ShiftCount),
476 BITFIELD (JumpAbsolute),
488 BITFIELD (Unspecified),
496 static const char *filename;
499 compare (const void *x, const void *y)
501 const bitfield *xp = (const bitfield *) x;
502 const bitfield *yp = (const bitfield *) y;
503 return xp->position - yp->position;
507 fail (const char *message, ...)
511 va_start (args, message);
512 fprintf (stderr, _("%s: Error: "), program_name);
513 vfprintf (stderr, message, args);
519 process_copyright (FILE *fp)
521 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
522 /* Copyright 2007, 2008, 2009, 2010, 2011\n\
523 Free Software Foundation, Inc.\n\
525 This file is part of the GNU opcodes library.\n\
527 This library is free software; you can redistribute it and/or modify\n\
528 it under the terms of the GNU General Public License as published by\n\
529 the Free Software Foundation; either version 3, or (at your option)\n\
530 any later version.\n\
532 It is distributed in the hope that it will be useful, but WITHOUT\n\
533 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
534 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
535 License for more details.\n\
537 You should have received a copy of the GNU General Public License\n\
538 along with this program; if not, write to the Free Software\n\
539 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
540 MA 02110-1301, USA. */\n");
543 /* Remove leading white spaces. */
546 remove_leading_whitespaces (char *str)
548 while (ISSPACE (*str))
553 /* Remove trailing white spaces. */
556 remove_trailing_whitespaces (char *str)
558 size_t last = strlen (str);
566 if (ISSPACE (str [last]))
574 /* Find next field separated by SEP and terminate it. Return a
575 pointer to the one after it. */
578 next_field (char *str, char sep, char **next, char *last)
582 p = remove_leading_whitespaces (str);
583 for (str = p; *str != sep && *str != '\0'; str++);
586 remove_trailing_whitespaces (p);
597 set_bitfield (const char *f, bitfield *array, int value,
598 unsigned int size, int lineno)
602 if (strcmp (f, "CpuFP") == 0)
604 set_bitfield("Cpu387", array, value, size, lineno);
605 set_bitfield("Cpu287", array, value, size, lineno);
608 else if (strcmp (f, "Mmword") == 0)
610 else if (strcmp (f, "Oword") == 0)
613 for (i = 0; i < size; i++)
614 if (strcasecmp (array[i].name, f) == 0)
616 array[i].value = value;
622 const char *v = strchr (f, '=');
629 for (i = 0; i < size; i++)
630 if (strncasecmp (array[i].name, f, n) == 0)
632 value = strtol (v + 1, &end, 0);
635 array[i].value = value;
644 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
646 fail (_("Unknown bitfield: %s\n"), f);
650 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
651 int macro, const char *comma, const char *indent)
655 fprintf (table, "%s{ { ", indent);
657 for (i = 0; i < size - 1; i++)
659 fprintf (table, "%d, ", flags[i].value);
660 if (((i + 1) % 20) == 0)
662 /* We need \\ for macro. */
664 fprintf (table, " \\\n %s", indent);
666 fprintf (table, "\n %s", indent);
670 fprintf (table, "%d } }%s\n", flags[i].value, comma);
674 process_i386_cpu_flag (FILE *table, char *flag, int macro,
675 const char *comma, const char *indent,
678 char *str, *next, *last;
680 bitfield flags [ARRAY_SIZE (cpu_flags)];
682 /* Copy the default cpu flags. */
683 memcpy (flags, cpu_flags, sizeof (cpu_flags));
685 if (strcasecmp (flag, "unknown") == 0)
687 /* We turn on everything except for cpu64 in case of
688 CPU_UNKNOWN_FLAGS. */
689 for (i = 0; i < ARRAY_SIZE (flags); i++)
690 if (flags[i].position != Cpu64)
693 else if (flag[0] == '~')
695 last = flag + strlen (flag);
702 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
709 /* First we turn on everything except for cpu64. */
710 for (i = 0; i < ARRAY_SIZE (flags); i++)
711 if (flags[i].position != Cpu64)
714 /* Turn off selective bits. */
715 for (; next && next < last; )
717 str = next_field (next, '|', &next, last);
719 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
722 else if (strcmp (flag, "0"))
724 /* Turn on selective bits. */
725 last = flag + strlen (flag);
726 for (next = flag; next && next < last; )
728 str = next_field (next, '|', &next, last);
730 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
734 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
739 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
743 fprintf (table, " { ");
745 for (i = 0; i < size - 1; i++)
747 fprintf (table, "%d, ", modifier[i].value);
748 if (((i + 1) % 20) == 0)
749 fprintf (table, "\n ");
752 fprintf (table, "%d },\n", modifier[i].value);
756 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
758 char *str, *next, *last;
759 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
761 /* Copy the default opcode modifier. */
762 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
764 if (strcmp (mod, "0"))
766 last = mod + strlen (mod);
767 for (next = mod; next && next < last; )
769 str = next_field (next, '|', &next, last);
771 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
775 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
779 output_operand_type (FILE *table, bitfield *types, unsigned int size,
780 int macro, const char *indent)
784 fprintf (table, "{ { ");
786 for (i = 0; i < size - 1; i++)
788 fprintf (table, "%d, ", types[i].value);
789 if (((i + 1) % 20) == 0)
791 /* We need \\ for macro. */
793 fprintf (table, "\\\n%s", indent);
795 fprintf (table, "\n%s", indent);
799 fprintf (table, "%d } }", types[i].value);
803 process_i386_operand_type (FILE *table, char *op, int macro,
804 const char *indent, int lineno)
806 char *str, *next, *last;
807 bitfield types [ARRAY_SIZE (operand_types)];
809 /* Copy the default operand type. */
810 memcpy (types, operand_types, sizeof (types));
812 if (strcmp (op, "0"))
814 last = op + strlen (op);
815 for (next = op; next && next < last; )
817 str = next_field (next, '|', &next, last);
819 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
822 output_operand_type (table, types, ARRAY_SIZE (types), macro,
827 output_i386_opcode (FILE *table, const char *name, char *str,
828 char *last, int lineno)
831 char *operands, *base_opcode, *extension_opcode, *opcode_length;
832 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
834 /* Find number of operands. */
835 operands = next_field (str, ',', &str, last);
837 /* Find base_opcode. */
838 base_opcode = next_field (str, ',', &str, last);
840 /* Find extension_opcode. */
841 extension_opcode = next_field (str, ',', &str, last);
843 /* Find opcode_length. */
844 opcode_length = next_field (str, ',', &str, last);
846 /* Find cpu_flags. */
847 cpu_flags = next_field (str, ',', &str, last);
849 /* Find opcode_modifier. */
850 opcode_modifier = next_field (str, ',', &str, last);
852 /* Remove the first {. */
853 str = remove_leading_whitespaces (str);
856 str = remove_leading_whitespaces (str + 1);
860 /* There are at least "X}". */
864 /* Remove trailing white spaces and }. */
868 if (ISSPACE (str[i]) || str[i] == '}')
877 /* Find operand_types. */
878 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
882 operand_types [i] = NULL;
886 operand_types [i] = next_field (str, ',', &str, last);
887 if (*operand_types[i] == '0')
890 operand_types[i] = NULL;
895 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
896 name, operands, base_opcode, extension_opcode,
899 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
901 process_i386_opcode_modifier (table, opcode_modifier, lineno);
903 fprintf (table, " { ");
905 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
907 if (operand_types[i] == NULL || *operand_types[i] == '0')
910 process_i386_operand_type (table, "0", 0, "\t ", lineno);
915 fprintf (table, ",\n ");
917 process_i386_operand_type (table, operand_types[i], 0,
920 fprintf (table, " } },\n");
923 struct opcode_hash_entry
925 struct opcode_hash_entry *next;
931 /* Calculate the hash value of an opcode hash entry P. */
934 opcode_hash_hash (const void *p)
936 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
937 return htab_hash_string (entry->name);
940 /* Compare a string Q against an opcode hash entry P. */
943 opcode_hash_eq (const void *p, const void *q)
945 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
946 const char *name = (const char *) q;
947 return strcmp (name, entry->name) == 0;
951 process_i386_opcodes (FILE *table)
956 char *str, *p, *last, *name;
957 struct opcode_hash_entry **hash_slot, **entry, *next;
958 htab_t opcode_hash_table;
959 struct opcode_hash_entry **opcode_array;
960 unsigned int opcode_array_size = 1024;
963 filename = "i386-opc.tbl";
964 fp = fopen (filename, "r");
967 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
971 opcode_array = (struct opcode_hash_entry **)
972 xmalloc (sizeof (*opcode_array) * opcode_array_size);
974 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
975 opcode_hash_eq, NULL,
978 fprintf (table, "\n/* i386 opcode table. */\n\n");
979 fprintf (table, "const insn_template i386_optab[] =\n{\n");
981 /* Put everything on opcode array. */
984 if (fgets (buf, sizeof (buf), fp) == NULL)
989 p = remove_leading_whitespaces (buf);
992 str = strstr (p, "//");
996 /* Remove trailing white spaces. */
997 remove_trailing_whitespaces (p);
1002 /* Ignore comments. */
1010 last = p + strlen (p);
1013 name = next_field (p, ',', &str, last);
1015 /* Get the slot in hash table. */
1016 hash_slot = (struct opcode_hash_entry **)
1017 htab_find_slot_with_hash (opcode_hash_table, name,
1018 htab_hash_string (name),
1021 if (*hash_slot == NULL)
1023 /* It is the new one. Put it on opcode array. */
1024 if (i >= opcode_array_size)
1026 /* Grow the opcode array when needed. */
1027 opcode_array_size += 1024;
1028 opcode_array = (struct opcode_hash_entry **)
1029 xrealloc (opcode_array,
1030 sizeof (*opcode_array) * opcode_array_size);
1033 opcode_array[i] = (struct opcode_hash_entry *)
1034 xmalloc (sizeof (struct opcode_hash_entry));
1035 opcode_array[i]->next = NULL;
1036 opcode_array[i]->name = xstrdup (name);
1037 opcode_array[i]->opcode = xstrdup (str);
1038 opcode_array[i]->lineno = lineno;
1039 *hash_slot = opcode_array[i];
1044 /* Append it to the existing one. */
1046 while ((*entry) != NULL)
1047 entry = &(*entry)->next;
1048 *entry = (struct opcode_hash_entry *)
1049 xmalloc (sizeof (struct opcode_hash_entry));
1050 (*entry)->next = NULL;
1051 (*entry)->name = (*hash_slot)->name;
1052 (*entry)->opcode = xstrdup (str);
1053 (*entry)->lineno = lineno;
1057 /* Process opcode array. */
1058 for (j = 0; j < i; j++)
1060 for (next = opcode_array[j]; next; next = next->next)
1064 lineno = next->lineno;
1065 last = str + strlen (str);
1066 output_i386_opcode (table, name, str, last, lineno);
1072 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1074 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1076 process_i386_opcode_modifier (table, "0", -1);
1078 fprintf (table, " { ");
1079 process_i386_operand_type (table, "0", 0, "\t ", -1);
1080 fprintf (table, " } }\n");
1082 fprintf (table, "};\n");
1086 process_i386_registers (FILE *table)
1090 char *str, *p, *last;
1091 char *reg_name, *reg_type, *reg_flags, *reg_num;
1092 char *dw2_32_num, *dw2_64_num;
1095 filename = "i386-reg.tbl";
1096 fp = fopen (filename, "r");
1098 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1101 fprintf (table, "\n/* i386 register table. */\n\n");
1102 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1106 if (fgets (buf, sizeof (buf), fp) == NULL)
1111 p = remove_leading_whitespaces (buf);
1113 /* Skip comments. */
1114 str = strstr (p, "//");
1118 /* Remove trailing white spaces. */
1119 remove_trailing_whitespaces (p);
1124 fprintf (table, "%s\n", p);
1132 last = p + strlen (p);
1134 /* Find reg_name. */
1135 reg_name = next_field (p, ',', &str, last);
1137 /* Find reg_type. */
1138 reg_type = next_field (str, ',', &str, last);
1140 /* Find reg_flags. */
1141 reg_flags = next_field (str, ',', &str, last);
1144 reg_num = next_field (str, ',', &str, last);
1146 fprintf (table, " { \"%s\",\n ", reg_name);
1148 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1150 /* Find 32-bit Dwarf2 register number. */
1151 dw2_32_num = next_field (str, ',', &str, last);
1153 /* Find 64-bit Dwarf2 register number. */
1154 dw2_64_num = next_field (str, ',', &str, last);
1156 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1157 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1162 fprintf (table, "};\n");
1164 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1168 process_i386_initializers (void)
1171 FILE *fp = fopen ("i386-init.h", "w");
1175 fail (_("can't create i386-init.h, errno = %s\n"),
1178 process_copyright (fp);
1180 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1182 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1183 init = xstrdup (cpu_flag_init[i].init);
1184 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1188 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1190 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1191 init = xstrdup (operand_type_init[i].init);
1192 process_i386_operand_type (fp, init, 1, " ", -1);
1200 /* Program options. */
1201 #define OPTION_SRCDIR 200
1203 struct option long_options[] =
1205 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1206 {"debug", no_argument, NULL, 'd'},
1207 {"version", no_argument, NULL, 'V'},
1208 {"help", no_argument, NULL, 'h'},
1209 {0, no_argument, NULL, 0}
1213 print_version (void)
1215 printf ("%s: version 1.0\n", program_name);
1220 usage (FILE * stream, int status)
1222 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1228 main (int argc, char **argv)
1230 extern int chdir (char *);
1231 char *srcdir = NULL;
1235 program_name = *argv;
1236 xmalloc_set_program_name (program_name);
1238 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1263 if (chdir (srcdir) != 0)
1264 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1265 srcdir, xstrerror (errno));
1267 /* Check the unused bitfield in i386_cpu_flags. */
1269 c = CpuNumOfBits - CpuMax - 1;
1271 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1274 /* Check the unused bitfield in i386_operand_type. */
1276 c = OTNumOfBits - OTMax - 1;
1278 fail (_("%d unused bits in i386_operand_type.\n"), c);
1281 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1284 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1285 sizeof (opcode_modifiers [0]), compare);
1287 qsort (operand_types, ARRAY_SIZE (operand_types),
1288 sizeof (operand_types [0]), compare);
1290 table = fopen ("i386-tbl.h", "w");
1292 fail (_("can't create i386-tbl.h, errno = %s\n"),
1295 process_copyright (table);
1297 process_i386_opcodes (table);
1298 process_i386_registers (table);
1299 process_i386_initializers ();