1 /* Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013
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",
213 static initializer operand_type_init[] =
215 { "OPERAND_TYPE_NONE",
217 { "OPERAND_TYPE_REG8",
219 { "OPERAND_TYPE_REG16",
221 { "OPERAND_TYPE_REG32",
223 { "OPERAND_TYPE_REG64",
225 { "OPERAND_TYPE_IMM1",
227 { "OPERAND_TYPE_IMM8",
229 { "OPERAND_TYPE_IMM8S",
231 { "OPERAND_TYPE_IMM16",
233 { "OPERAND_TYPE_IMM32",
235 { "OPERAND_TYPE_IMM32S",
237 { "OPERAND_TYPE_IMM64",
239 { "OPERAND_TYPE_BASEINDEX",
241 { "OPERAND_TYPE_DISP8",
243 { "OPERAND_TYPE_DISP16",
245 { "OPERAND_TYPE_DISP32",
247 { "OPERAND_TYPE_DISP32S",
249 { "OPERAND_TYPE_DISP64",
251 { "OPERAND_TYPE_INOUTPORTREG",
253 { "OPERAND_TYPE_SHIFTCOUNT",
255 { "OPERAND_TYPE_CONTROL",
257 { "OPERAND_TYPE_TEST",
259 { "OPERAND_TYPE_DEBUG",
261 { "OPERAND_TYPE_FLOATREG",
263 { "OPERAND_TYPE_FLOATACC",
265 { "OPERAND_TYPE_SREG2",
267 { "OPERAND_TYPE_SREG3",
269 { "OPERAND_TYPE_ACC",
271 { "OPERAND_TYPE_JUMPABSOLUTE",
273 { "OPERAND_TYPE_REGMMX",
275 { "OPERAND_TYPE_REGXMM",
277 { "OPERAND_TYPE_REGYMM",
279 { "OPERAND_TYPE_ESSEG",
281 { "OPERAND_TYPE_ACC32",
283 { "OPERAND_TYPE_ACC64",
285 { "OPERAND_TYPE_INOUTPORTREG",
287 { "OPERAND_TYPE_REG16_INOUTPORTREG",
288 "Reg16|InOutPortReg" },
289 { "OPERAND_TYPE_DISP16_32",
291 { "OPERAND_TYPE_ANYDISP",
292 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
293 { "OPERAND_TYPE_IMM16_32",
295 { "OPERAND_TYPE_IMM16_32S",
297 { "OPERAND_TYPE_IMM16_32_32S",
298 "Imm16|Imm32|Imm32S" },
299 { "OPERAND_TYPE_IMM32_64",
301 { "OPERAND_TYPE_IMM32_32S_DISP32",
302 "Imm32|Imm32S|Disp32" },
303 { "OPERAND_TYPE_IMM64_DISP64",
305 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
306 "Imm32|Imm32S|Imm64|Disp32" },
307 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
308 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
309 { "OPERAND_TYPE_VEC_IMM4",
313 typedef struct bitfield
320 #define BITFIELD(n) { n, 0, #n }
322 static bitfield cpu_flags[] =
330 BITFIELD (CpuClflush),
332 BITFIELD (CpuSYSCALL),
337 BITFIELD (CpuFISTTP),
343 BITFIELD (CpuSSE4_1),
344 BITFIELD (CpuSSE4_2),
351 BITFIELD (Cpu3dnowA),
352 BITFIELD (CpuPadLock),
358 BITFIELD (CpuXsaveopt),
360 BITFIELD (CpuPCLMUL),
371 BITFIELD (CpuRdtscp),
372 BITFIELD (CpuFSGSBase),
379 BITFIELD (CpuINVPCID),
380 BITFIELD (CpuVMFUNC),
381 BITFIELD (CpuRDSEED),
383 BITFIELD (CpuPRFCHW),
388 BITFIELD (CpuUnused),
392 static bitfield opcode_modifiers[] =
398 BITFIELD (ShortForm),
400 BITFIELD (JumpDword),
402 BITFIELD (JumpInterSegment),
409 BITFIELD (CheckRegSize),
410 BITFIELD (IgnoreSize),
411 BITFIELD (DefaultSize),
420 BITFIELD (IsLockable),
421 BITFIELD (RegKludge),
422 BITFIELD (FirstXmm0),
423 BITFIELD (Implicit1stXmm0),
424 BITFIELD (RepPrefixOk),
425 BITFIELD (HLEPrefixOk),
428 BITFIELD (AddrPrefixOp0),
437 BITFIELD (VexOpcode),
438 BITFIELD (VexSources),
439 BITFIELD (VexImmExt),
444 BITFIELD (ATTMnemonic),
445 BITFIELD (ATTSyntax),
446 BITFIELD (IntelSyntax),
449 static bitfield operand_types[] =
466 BITFIELD (BaseIndex),
472 BITFIELD (InOutPortReg),
473 BITFIELD (ShiftCount),
481 BITFIELD (JumpAbsolute),
493 BITFIELD (Unspecified),
501 static const char *filename;
504 compare (const void *x, const void *y)
506 const bitfield *xp = (const bitfield *) x;
507 const bitfield *yp = (const bitfield *) y;
508 return xp->position - yp->position;
512 fail (const char *message, ...)
516 va_start (args, message);
517 fprintf (stderr, _("%s: Error: "), program_name);
518 vfprintf (stderr, message, args);
524 process_copyright (FILE *fp)
526 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
527 /* Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013\n\
528 Free Software Foundation, Inc.\n\
530 This file is part of the GNU opcodes library.\n\
532 This library is free software; you can redistribute it and/or modify\n\
533 it under the terms of the GNU General Public License as published by\n\
534 the Free Software Foundation; either version 3, or (at your option)\n\
535 any later version.\n\
537 It is distributed in the hope that it will be useful, but WITHOUT\n\
538 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
539 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
540 License for more details.\n\
542 You should have received a copy of the GNU General Public License\n\
543 along with this program; if not, write to the Free Software\n\
544 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
545 MA 02110-1301, USA. */\n");
548 /* Remove leading white spaces. */
551 remove_leading_whitespaces (char *str)
553 while (ISSPACE (*str))
558 /* Remove trailing white spaces. */
561 remove_trailing_whitespaces (char *str)
563 size_t last = strlen (str);
571 if (ISSPACE (str [last]))
579 /* Find next field separated by SEP and terminate it. Return a
580 pointer to the one after it. */
583 next_field (char *str, char sep, char **next, char *last)
587 p = remove_leading_whitespaces (str);
588 for (str = p; *str != sep && *str != '\0'; str++);
591 remove_trailing_whitespaces (p);
602 set_bitfield (const char *f, bitfield *array, int value,
603 unsigned int size, int lineno)
607 if (strcmp (f, "CpuFP") == 0)
609 set_bitfield("Cpu387", array, value, size, lineno);
610 set_bitfield("Cpu287", array, value, size, lineno);
613 else if (strcmp (f, "Mmword") == 0)
615 else if (strcmp (f, "Oword") == 0)
618 for (i = 0; i < size; i++)
619 if (strcasecmp (array[i].name, f) == 0)
621 array[i].value = value;
627 const char *v = strchr (f, '=');
634 for (i = 0; i < size; i++)
635 if (strncasecmp (array[i].name, f, n) == 0)
637 value = strtol (v + 1, &end, 0);
640 array[i].value = value;
649 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
651 fail (_("Unknown bitfield: %s\n"), f);
655 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
656 int macro, const char *comma, const char *indent)
660 fprintf (table, "%s{ { ", indent);
662 for (i = 0; i < size - 1; i++)
664 fprintf (table, "%d, ", flags[i].value);
665 if (((i + 1) % 20) == 0)
667 /* We need \\ for macro. */
669 fprintf (table, " \\\n %s", indent);
671 fprintf (table, "\n %s", indent);
675 fprintf (table, "%d } }%s\n", flags[i].value, comma);
679 process_i386_cpu_flag (FILE *table, char *flag, int macro,
680 const char *comma, const char *indent,
683 char *str, *next, *last;
685 bitfield flags [ARRAY_SIZE (cpu_flags)];
687 /* Copy the default cpu flags. */
688 memcpy (flags, cpu_flags, sizeof (cpu_flags));
690 if (strcasecmp (flag, "unknown") == 0)
692 /* We turn on everything except for cpu64 in case of
693 CPU_UNKNOWN_FLAGS. */
694 for (i = 0; i < ARRAY_SIZE (flags); i++)
695 if (flags[i].position != Cpu64)
698 else if (flag[0] == '~')
700 last = flag + strlen (flag);
707 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
714 /* First we turn on everything except for cpu64. */
715 for (i = 0; i < ARRAY_SIZE (flags); i++)
716 if (flags[i].position != Cpu64)
719 /* Turn off selective bits. */
720 for (; next && next < last; )
722 str = next_field (next, '|', &next, last);
724 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
727 else if (strcmp (flag, "0"))
729 /* Turn on selective bits. */
730 last = flag + strlen (flag);
731 for (next = flag; next && next < last; )
733 str = next_field (next, '|', &next, last);
735 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
739 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
744 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
748 fprintf (table, " { ");
750 for (i = 0; i < size - 1; i++)
752 fprintf (table, "%d, ", modifier[i].value);
753 if (((i + 1) % 20) == 0)
754 fprintf (table, "\n ");
757 fprintf (table, "%d },\n", modifier[i].value);
761 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
763 char *str, *next, *last;
764 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
766 /* Copy the default opcode modifier. */
767 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
769 if (strcmp (mod, "0"))
771 last = mod + strlen (mod);
772 for (next = mod; next && next < last; )
774 str = next_field (next, '|', &next, last);
776 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
780 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
784 output_operand_type (FILE *table, bitfield *types, unsigned int size,
785 int macro, const char *indent)
789 fprintf (table, "{ { ");
791 for (i = 0; i < size - 1; i++)
793 fprintf (table, "%d, ", types[i].value);
794 if (((i + 1) % 20) == 0)
796 /* We need \\ for macro. */
798 fprintf (table, "\\\n%s", indent);
800 fprintf (table, "\n%s", indent);
804 fprintf (table, "%d } }", types[i].value);
808 process_i386_operand_type (FILE *table, char *op, int macro,
809 const char *indent, int lineno)
811 char *str, *next, *last;
812 bitfield types [ARRAY_SIZE (operand_types)];
814 /* Copy the default operand type. */
815 memcpy (types, operand_types, sizeof (types));
817 if (strcmp (op, "0"))
819 last = op + strlen (op);
820 for (next = op; next && next < last; )
822 str = next_field (next, '|', &next, last);
824 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
827 output_operand_type (table, types, ARRAY_SIZE (types), macro,
832 output_i386_opcode (FILE *table, const char *name, char *str,
833 char *last, int lineno)
836 char *operands, *base_opcode, *extension_opcode, *opcode_length;
837 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
839 /* Find number of operands. */
840 operands = next_field (str, ',', &str, last);
842 /* Find base_opcode. */
843 base_opcode = next_field (str, ',', &str, last);
845 /* Find extension_opcode. */
846 extension_opcode = next_field (str, ',', &str, last);
848 /* Find opcode_length. */
849 opcode_length = next_field (str, ',', &str, last);
851 /* Find cpu_flags. */
852 cpu_flags = next_field (str, ',', &str, last);
854 /* Find opcode_modifier. */
855 opcode_modifier = next_field (str, ',', &str, last);
857 /* Remove the first {. */
858 str = remove_leading_whitespaces (str);
861 str = remove_leading_whitespaces (str + 1);
865 /* There are at least "X}". */
869 /* Remove trailing white spaces and }. */
873 if (ISSPACE (str[i]) || str[i] == '}')
882 /* Find operand_types. */
883 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
887 operand_types [i] = NULL;
891 operand_types [i] = next_field (str, ',', &str, last);
892 if (*operand_types[i] == '0')
895 operand_types[i] = NULL;
900 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
901 name, operands, base_opcode, extension_opcode,
904 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
906 process_i386_opcode_modifier (table, opcode_modifier, lineno);
908 fprintf (table, " { ");
910 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
912 if (operand_types[i] == NULL || *operand_types[i] == '0')
915 process_i386_operand_type (table, "0", 0, "\t ", lineno);
920 fprintf (table, ",\n ");
922 process_i386_operand_type (table, operand_types[i], 0,
925 fprintf (table, " } },\n");
928 struct opcode_hash_entry
930 struct opcode_hash_entry *next;
936 /* Calculate the hash value of an opcode hash entry P. */
939 opcode_hash_hash (const void *p)
941 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
942 return htab_hash_string (entry->name);
945 /* Compare a string Q against an opcode hash entry P. */
948 opcode_hash_eq (const void *p, const void *q)
950 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
951 const char *name = (const char *) q;
952 return strcmp (name, entry->name) == 0;
956 process_i386_opcodes (FILE *table)
961 char *str, *p, *last, *name;
962 struct opcode_hash_entry **hash_slot, **entry, *next;
963 htab_t opcode_hash_table;
964 struct opcode_hash_entry **opcode_array;
965 unsigned int opcode_array_size = 1024;
968 filename = "i386-opc.tbl";
969 fp = fopen (filename, "r");
972 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
976 opcode_array = (struct opcode_hash_entry **)
977 xmalloc (sizeof (*opcode_array) * opcode_array_size);
979 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
980 opcode_hash_eq, NULL,
983 fprintf (table, "\n/* i386 opcode table. */\n\n");
984 fprintf (table, "const insn_template i386_optab[] =\n{\n");
986 /* Put everything on opcode array. */
989 if (fgets (buf, sizeof (buf), fp) == NULL)
994 p = remove_leading_whitespaces (buf);
997 str = strstr (p, "//");
1001 /* Remove trailing white spaces. */
1002 remove_trailing_whitespaces (p);
1007 /* Ignore comments. */
1015 last = p + strlen (p);
1018 name = next_field (p, ',', &str, last);
1020 /* Get the slot in hash table. */
1021 hash_slot = (struct opcode_hash_entry **)
1022 htab_find_slot_with_hash (opcode_hash_table, name,
1023 htab_hash_string (name),
1026 if (*hash_slot == NULL)
1028 /* It is the new one. Put it on opcode array. */
1029 if (i >= opcode_array_size)
1031 /* Grow the opcode array when needed. */
1032 opcode_array_size += 1024;
1033 opcode_array = (struct opcode_hash_entry **)
1034 xrealloc (opcode_array,
1035 sizeof (*opcode_array) * opcode_array_size);
1038 opcode_array[i] = (struct opcode_hash_entry *)
1039 xmalloc (sizeof (struct opcode_hash_entry));
1040 opcode_array[i]->next = NULL;
1041 opcode_array[i]->name = xstrdup (name);
1042 opcode_array[i]->opcode = xstrdup (str);
1043 opcode_array[i]->lineno = lineno;
1044 *hash_slot = opcode_array[i];
1049 /* Append it to the existing one. */
1051 while ((*entry) != NULL)
1052 entry = &(*entry)->next;
1053 *entry = (struct opcode_hash_entry *)
1054 xmalloc (sizeof (struct opcode_hash_entry));
1055 (*entry)->next = NULL;
1056 (*entry)->name = (*hash_slot)->name;
1057 (*entry)->opcode = xstrdup (str);
1058 (*entry)->lineno = lineno;
1062 /* Process opcode array. */
1063 for (j = 0; j < i; j++)
1065 for (next = opcode_array[j]; next; next = next->next)
1069 lineno = next->lineno;
1070 last = str + strlen (str);
1071 output_i386_opcode (table, name, str, last, lineno);
1077 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1079 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1081 process_i386_opcode_modifier (table, "0", -1);
1083 fprintf (table, " { ");
1084 process_i386_operand_type (table, "0", 0, "\t ", -1);
1085 fprintf (table, " } }\n");
1087 fprintf (table, "};\n");
1091 process_i386_registers (FILE *table)
1095 char *str, *p, *last;
1096 char *reg_name, *reg_type, *reg_flags, *reg_num;
1097 char *dw2_32_num, *dw2_64_num;
1100 filename = "i386-reg.tbl";
1101 fp = fopen (filename, "r");
1103 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1106 fprintf (table, "\n/* i386 register table. */\n\n");
1107 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1111 if (fgets (buf, sizeof (buf), fp) == NULL)
1116 p = remove_leading_whitespaces (buf);
1118 /* Skip comments. */
1119 str = strstr (p, "//");
1123 /* Remove trailing white spaces. */
1124 remove_trailing_whitespaces (p);
1129 fprintf (table, "%s\n", p);
1137 last = p + strlen (p);
1139 /* Find reg_name. */
1140 reg_name = next_field (p, ',', &str, last);
1142 /* Find reg_type. */
1143 reg_type = next_field (str, ',', &str, last);
1145 /* Find reg_flags. */
1146 reg_flags = next_field (str, ',', &str, last);
1149 reg_num = next_field (str, ',', &str, last);
1151 fprintf (table, " { \"%s\",\n ", reg_name);
1153 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1155 /* Find 32-bit Dwarf2 register number. */
1156 dw2_32_num = next_field (str, ',', &str, last);
1158 /* Find 64-bit Dwarf2 register number. */
1159 dw2_64_num = next_field (str, ',', &str, last);
1161 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1162 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1167 fprintf (table, "};\n");
1169 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1173 process_i386_initializers (void)
1176 FILE *fp = fopen ("i386-init.h", "w");
1180 fail (_("can't create i386-init.h, errno = %s\n"),
1183 process_copyright (fp);
1185 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1187 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1188 init = xstrdup (cpu_flag_init[i].init);
1189 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1193 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1195 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1196 init = xstrdup (operand_type_init[i].init);
1197 process_i386_operand_type (fp, init, 1, " ", -1);
1205 /* Program options. */
1206 #define OPTION_SRCDIR 200
1208 struct option long_options[] =
1210 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1211 {"debug", no_argument, NULL, 'd'},
1212 {"version", no_argument, NULL, 'V'},
1213 {"help", no_argument, NULL, 'h'},
1214 {0, no_argument, NULL, 0}
1218 print_version (void)
1220 printf ("%s: version 1.0\n", program_name);
1225 usage (FILE * stream, int status)
1227 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1233 main (int argc, char **argv)
1235 extern int chdir (char *);
1236 char *srcdir = NULL;
1240 program_name = *argv;
1241 xmalloc_set_program_name (program_name);
1243 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1268 if (chdir (srcdir) != 0)
1269 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1270 srcdir, xstrerror (errno));
1272 /* Check the unused bitfield in i386_cpu_flags. */
1274 c = CpuNumOfBits - CpuMax - 1;
1276 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1279 /* Check the unused bitfield in i386_operand_type. */
1281 c = OTNumOfBits - OTMax - 1;
1283 fail (_("%d unused bits in i386_operand_type.\n"), c);
1286 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1289 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1290 sizeof (opcode_modifiers [0]), compare);
1292 qsort (operand_types, ARRAY_SIZE (operand_types),
1293 sizeof (operand_types [0]), compare);
1295 table = fopen ("i386-tbl.h", "w");
1297 fail (_("can't create i386-tbl.h, errno = %s\n"),
1300 process_copyright (table);
1302 process_i386_opcodes (table);
1303 process_i386_registers (table);
1304 process_i386_initializers ();