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|CpuFSGSBase" },
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",
217 static initializer operand_type_init[] =
219 { "OPERAND_TYPE_NONE",
221 { "OPERAND_TYPE_REG8",
223 { "OPERAND_TYPE_REG16",
225 { "OPERAND_TYPE_REG32",
227 { "OPERAND_TYPE_REG64",
229 { "OPERAND_TYPE_IMM1",
231 { "OPERAND_TYPE_IMM8",
233 { "OPERAND_TYPE_IMM8S",
235 { "OPERAND_TYPE_IMM16",
237 { "OPERAND_TYPE_IMM32",
239 { "OPERAND_TYPE_IMM32S",
241 { "OPERAND_TYPE_IMM64",
243 { "OPERAND_TYPE_BASEINDEX",
245 { "OPERAND_TYPE_DISP8",
247 { "OPERAND_TYPE_DISP16",
249 { "OPERAND_TYPE_DISP32",
251 { "OPERAND_TYPE_DISP32S",
253 { "OPERAND_TYPE_DISP64",
255 { "OPERAND_TYPE_INOUTPORTREG",
257 { "OPERAND_TYPE_SHIFTCOUNT",
259 { "OPERAND_TYPE_CONTROL",
261 { "OPERAND_TYPE_TEST",
263 { "OPERAND_TYPE_DEBUG",
265 { "OPERAND_TYPE_FLOATREG",
267 { "OPERAND_TYPE_FLOATACC",
269 { "OPERAND_TYPE_SREG2",
271 { "OPERAND_TYPE_SREG3",
273 { "OPERAND_TYPE_ACC",
275 { "OPERAND_TYPE_JUMPABSOLUTE",
277 { "OPERAND_TYPE_REGMMX",
279 { "OPERAND_TYPE_REGXMM",
281 { "OPERAND_TYPE_REGYMM",
283 { "OPERAND_TYPE_ESSEG",
285 { "OPERAND_TYPE_ACC32",
287 { "OPERAND_TYPE_ACC64",
289 { "OPERAND_TYPE_INOUTPORTREG",
291 { "OPERAND_TYPE_REG16_INOUTPORTREG",
292 "Reg16|InOutPortReg" },
293 { "OPERAND_TYPE_DISP16_32",
295 { "OPERAND_TYPE_ANYDISP",
296 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
297 { "OPERAND_TYPE_IMM16_32",
299 { "OPERAND_TYPE_IMM16_32S",
301 { "OPERAND_TYPE_IMM16_32_32S",
302 "Imm16|Imm32|Imm32S" },
303 { "OPERAND_TYPE_IMM32_64",
305 { "OPERAND_TYPE_IMM32_32S_DISP32",
306 "Imm32|Imm32S|Disp32" },
307 { "OPERAND_TYPE_IMM64_DISP64",
309 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
310 "Imm32|Imm32S|Imm64|Disp32" },
311 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
312 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
313 { "OPERAND_TYPE_VEC_IMM4",
315 { "OPERAND_TYPE_REGBND",
319 typedef struct bitfield
326 #define BITFIELD(n) { n, 0, #n }
328 static bitfield cpu_flags[] =
336 BITFIELD (CpuClflush),
338 BITFIELD (CpuSYSCALL),
343 BITFIELD (CpuFISTTP),
349 BITFIELD (CpuSSE4_1),
350 BITFIELD (CpuSSE4_2),
357 BITFIELD (Cpu3dnowA),
358 BITFIELD (CpuPadLock),
364 BITFIELD (CpuXsaveopt),
366 BITFIELD (CpuPCLMUL),
377 BITFIELD (CpuRdtscp),
378 BITFIELD (CpuFSGSBase),
385 BITFIELD (CpuINVPCID),
386 BITFIELD (CpuVMFUNC),
387 BITFIELD (CpuRDSEED),
389 BITFIELD (CpuPRFCHW),
396 BITFIELD (CpuUnused),
400 static bitfield opcode_modifiers[] =
406 BITFIELD (ShortForm),
408 BITFIELD (JumpDword),
410 BITFIELD (JumpInterSegment),
417 BITFIELD (CheckRegSize),
418 BITFIELD (IgnoreSize),
419 BITFIELD (DefaultSize),
428 BITFIELD (BNDPrefixOk),
429 BITFIELD (IsLockable),
430 BITFIELD (RegKludge),
431 BITFIELD (FirstXmm0),
432 BITFIELD (Implicit1stXmm0),
433 BITFIELD (RepPrefixOk),
434 BITFIELD (HLEPrefixOk),
437 BITFIELD (AddrPrefixOp0),
446 BITFIELD (VexOpcode),
447 BITFIELD (VexSources),
448 BITFIELD (VexImmExt),
453 BITFIELD (ATTMnemonic),
454 BITFIELD (ATTSyntax),
455 BITFIELD (IntelSyntax),
458 static bitfield operand_types[] =
475 BITFIELD (BaseIndex),
481 BITFIELD (InOutPortReg),
482 BITFIELD (ShiftCount),
490 BITFIELD (JumpAbsolute),
502 BITFIELD (Unspecified),
511 static const char *filename;
514 compare (const void *x, const void *y)
516 const bitfield *xp = (const bitfield *) x;
517 const bitfield *yp = (const bitfield *) y;
518 return xp->position - yp->position;
522 fail (const char *message, ...)
526 va_start (args, message);
527 fprintf (stderr, _("%s: Error: "), program_name);
528 vfprintf (stderr, message, args);
534 process_copyright (FILE *fp)
536 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
537 /* Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013\n\
538 Free Software Foundation, Inc.\n\
540 This file is part of the GNU opcodes library.\n\
542 This library is free software; you can redistribute it and/or modify\n\
543 it under the terms of the GNU General Public License as published by\n\
544 the Free Software Foundation; either version 3, or (at your option)\n\
545 any later version.\n\
547 It is distributed in the hope that it will be useful, but WITHOUT\n\
548 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
549 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
550 License for more details.\n\
552 You should have received a copy of the GNU General Public License\n\
553 along with this program; if not, write to the Free Software\n\
554 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
555 MA 02110-1301, USA. */\n");
558 /* Remove leading white spaces. */
561 remove_leading_whitespaces (char *str)
563 while (ISSPACE (*str))
568 /* Remove trailing white spaces. */
571 remove_trailing_whitespaces (char *str)
573 size_t last = strlen (str);
581 if (ISSPACE (str [last]))
589 /* Find next field separated by SEP and terminate it. Return a
590 pointer to the one after it. */
593 next_field (char *str, char sep, char **next, char *last)
597 p = remove_leading_whitespaces (str);
598 for (str = p; *str != sep && *str != '\0'; str++);
601 remove_trailing_whitespaces (p);
612 set_bitfield (const char *f, bitfield *array, int value,
613 unsigned int size, int lineno)
617 if (strcmp (f, "CpuFP") == 0)
619 set_bitfield("Cpu387", array, value, size, lineno);
620 set_bitfield("Cpu287", array, value, size, lineno);
623 else if (strcmp (f, "Mmword") == 0)
625 else if (strcmp (f, "Oword") == 0)
628 for (i = 0; i < size; i++)
629 if (strcasecmp (array[i].name, f) == 0)
631 array[i].value = value;
637 const char *v = strchr (f, '=');
644 for (i = 0; i < size; i++)
645 if (strncasecmp (array[i].name, f, n) == 0)
647 value = strtol (v + 1, &end, 0);
650 array[i].value = value;
659 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
661 fail (_("Unknown bitfield: %s\n"), f);
665 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
666 int macro, const char *comma, const char *indent)
670 fprintf (table, "%s{ { ", indent);
672 for (i = 0; i < size - 1; i++)
674 fprintf (table, "%d, ", flags[i].value);
675 if (((i + 1) % 20) == 0)
677 /* We need \\ for macro. */
679 fprintf (table, " \\\n %s", indent);
681 fprintf (table, "\n %s", indent);
685 fprintf (table, "%d } }%s\n", flags[i].value, comma);
689 process_i386_cpu_flag (FILE *table, char *flag, int macro,
690 const char *comma, const char *indent,
693 char *str, *next, *last;
695 bitfield flags [ARRAY_SIZE (cpu_flags)];
697 /* Copy the default cpu flags. */
698 memcpy (flags, cpu_flags, sizeof (cpu_flags));
700 if (strcasecmp (flag, "unknown") == 0)
702 /* We turn on everything except for cpu64 in case of
703 CPU_UNKNOWN_FLAGS. */
704 for (i = 0; i < ARRAY_SIZE (flags); i++)
705 if (flags[i].position != Cpu64)
708 else if (flag[0] == '~')
710 last = flag + strlen (flag);
717 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
724 /* First we turn on everything except for cpu64. */
725 for (i = 0; i < ARRAY_SIZE (flags); i++)
726 if (flags[i].position != Cpu64)
729 /* Turn off selective bits. */
730 for (; next && next < last; )
732 str = next_field (next, '|', &next, last);
734 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
737 else if (strcmp (flag, "0"))
739 /* Turn on selective bits. */
740 last = flag + strlen (flag);
741 for (next = flag; next && next < last; )
743 str = next_field (next, '|', &next, last);
745 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
749 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
754 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
758 fprintf (table, " { ");
760 for (i = 0; i < size - 1; i++)
762 fprintf (table, "%d, ", modifier[i].value);
763 if (((i + 1) % 20) == 0)
764 fprintf (table, "\n ");
767 fprintf (table, "%d },\n", modifier[i].value);
771 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
773 char *str, *next, *last;
774 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
776 /* Copy the default opcode modifier. */
777 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
779 if (strcmp (mod, "0"))
781 last = mod + strlen (mod);
782 for (next = mod; next && next < last; )
784 str = next_field (next, '|', &next, last);
786 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
790 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
794 output_operand_type (FILE *table, bitfield *types, unsigned int size,
795 int macro, const char *indent)
799 fprintf (table, "{ { ");
801 for (i = 0; i < size - 1; i++)
803 fprintf (table, "%d, ", types[i].value);
804 if (((i + 1) % 20) == 0)
806 /* We need \\ for macro. */
808 fprintf (table, "\\\n%s", indent);
810 fprintf (table, "\n%s", indent);
814 fprintf (table, "%d } }", types[i].value);
818 process_i386_operand_type (FILE *table, char *op, int macro,
819 const char *indent, int lineno)
821 char *str, *next, *last;
822 bitfield types [ARRAY_SIZE (operand_types)];
824 /* Copy the default operand type. */
825 memcpy (types, operand_types, sizeof (types));
827 if (strcmp (op, "0"))
829 last = op + strlen (op);
830 for (next = op; next && next < last; )
832 str = next_field (next, '|', &next, last);
834 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
837 output_operand_type (table, types, ARRAY_SIZE (types), macro,
842 output_i386_opcode (FILE *table, const char *name, char *str,
843 char *last, int lineno)
846 char *operands, *base_opcode, *extension_opcode, *opcode_length;
847 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
849 /* Find number of operands. */
850 operands = next_field (str, ',', &str, last);
852 /* Find base_opcode. */
853 base_opcode = next_field (str, ',', &str, last);
855 /* Find extension_opcode. */
856 extension_opcode = next_field (str, ',', &str, last);
858 /* Find opcode_length. */
859 opcode_length = next_field (str, ',', &str, last);
861 /* Find cpu_flags. */
862 cpu_flags = next_field (str, ',', &str, last);
864 /* Find opcode_modifier. */
865 opcode_modifier = next_field (str, ',', &str, last);
867 /* Remove the first {. */
868 str = remove_leading_whitespaces (str);
871 str = remove_leading_whitespaces (str + 1);
875 /* There are at least "X}". */
879 /* Remove trailing white spaces and }. */
883 if (ISSPACE (str[i]) || str[i] == '}')
892 /* Find operand_types. */
893 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
897 operand_types [i] = NULL;
901 operand_types [i] = next_field (str, ',', &str, last);
902 if (*operand_types[i] == '0')
905 operand_types[i] = NULL;
910 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
911 name, operands, base_opcode, extension_opcode,
914 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
916 process_i386_opcode_modifier (table, opcode_modifier, lineno);
918 fprintf (table, " { ");
920 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
922 if (operand_types[i] == NULL || *operand_types[i] == '0')
925 process_i386_operand_type (table, "0", 0, "\t ", lineno);
930 fprintf (table, ",\n ");
932 process_i386_operand_type (table, operand_types[i], 0,
935 fprintf (table, " } },\n");
938 struct opcode_hash_entry
940 struct opcode_hash_entry *next;
946 /* Calculate the hash value of an opcode hash entry P. */
949 opcode_hash_hash (const void *p)
951 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
952 return htab_hash_string (entry->name);
955 /* Compare a string Q against an opcode hash entry P. */
958 opcode_hash_eq (const void *p, const void *q)
960 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
961 const char *name = (const char *) q;
962 return strcmp (name, entry->name) == 0;
966 process_i386_opcodes (FILE *table)
971 char *str, *p, *last, *name;
972 struct opcode_hash_entry **hash_slot, **entry, *next;
973 htab_t opcode_hash_table;
974 struct opcode_hash_entry **opcode_array;
975 unsigned int opcode_array_size = 1024;
978 filename = "i386-opc.tbl";
979 fp = fopen (filename, "r");
982 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
986 opcode_array = (struct opcode_hash_entry **)
987 xmalloc (sizeof (*opcode_array) * opcode_array_size);
989 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
990 opcode_hash_eq, NULL,
993 fprintf (table, "\n/* i386 opcode table. */\n\n");
994 fprintf (table, "const insn_template i386_optab[] =\n{\n");
996 /* Put everything on opcode array. */
999 if (fgets (buf, sizeof (buf), fp) == NULL)
1004 p = remove_leading_whitespaces (buf);
1006 /* Skip comments. */
1007 str = strstr (p, "//");
1011 /* Remove trailing white spaces. */
1012 remove_trailing_whitespaces (p);
1017 /* Ignore comments. */
1025 last = p + strlen (p);
1028 name = next_field (p, ',', &str, last);
1030 /* Get the slot in hash table. */
1031 hash_slot = (struct opcode_hash_entry **)
1032 htab_find_slot_with_hash (opcode_hash_table, name,
1033 htab_hash_string (name),
1036 if (*hash_slot == NULL)
1038 /* It is the new one. Put it on opcode array. */
1039 if (i >= opcode_array_size)
1041 /* Grow the opcode array when needed. */
1042 opcode_array_size += 1024;
1043 opcode_array = (struct opcode_hash_entry **)
1044 xrealloc (opcode_array,
1045 sizeof (*opcode_array) * opcode_array_size);
1048 opcode_array[i] = (struct opcode_hash_entry *)
1049 xmalloc (sizeof (struct opcode_hash_entry));
1050 opcode_array[i]->next = NULL;
1051 opcode_array[i]->name = xstrdup (name);
1052 opcode_array[i]->opcode = xstrdup (str);
1053 opcode_array[i]->lineno = lineno;
1054 *hash_slot = opcode_array[i];
1059 /* Append it to the existing one. */
1061 while ((*entry) != NULL)
1062 entry = &(*entry)->next;
1063 *entry = (struct opcode_hash_entry *)
1064 xmalloc (sizeof (struct opcode_hash_entry));
1065 (*entry)->next = NULL;
1066 (*entry)->name = (*hash_slot)->name;
1067 (*entry)->opcode = xstrdup (str);
1068 (*entry)->lineno = lineno;
1072 /* Process opcode array. */
1073 for (j = 0; j < i; j++)
1075 for (next = opcode_array[j]; next; next = next->next)
1079 lineno = next->lineno;
1080 last = str + strlen (str);
1081 output_i386_opcode (table, name, str, last, lineno);
1087 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1089 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1091 process_i386_opcode_modifier (table, "0", -1);
1093 fprintf (table, " { ");
1094 process_i386_operand_type (table, "0", 0, "\t ", -1);
1095 fprintf (table, " } }\n");
1097 fprintf (table, "};\n");
1101 process_i386_registers (FILE *table)
1105 char *str, *p, *last;
1106 char *reg_name, *reg_type, *reg_flags, *reg_num;
1107 char *dw2_32_num, *dw2_64_num;
1110 filename = "i386-reg.tbl";
1111 fp = fopen (filename, "r");
1113 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1116 fprintf (table, "\n/* i386 register table. */\n\n");
1117 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1121 if (fgets (buf, sizeof (buf), fp) == NULL)
1126 p = remove_leading_whitespaces (buf);
1128 /* Skip comments. */
1129 str = strstr (p, "//");
1133 /* Remove trailing white spaces. */
1134 remove_trailing_whitespaces (p);
1139 fprintf (table, "%s\n", p);
1147 last = p + strlen (p);
1149 /* Find reg_name. */
1150 reg_name = next_field (p, ',', &str, last);
1152 /* Find reg_type. */
1153 reg_type = next_field (str, ',', &str, last);
1155 /* Find reg_flags. */
1156 reg_flags = next_field (str, ',', &str, last);
1159 reg_num = next_field (str, ',', &str, last);
1161 fprintf (table, " { \"%s\",\n ", reg_name);
1163 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1165 /* Find 32-bit Dwarf2 register number. */
1166 dw2_32_num = next_field (str, ',', &str, last);
1168 /* Find 64-bit Dwarf2 register number. */
1169 dw2_64_num = next_field (str, ',', &str, last);
1171 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1172 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1177 fprintf (table, "};\n");
1179 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1183 process_i386_initializers (void)
1186 FILE *fp = fopen ("i386-init.h", "w");
1190 fail (_("can't create i386-init.h, errno = %s\n"),
1193 process_copyright (fp);
1195 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1197 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1198 init = xstrdup (cpu_flag_init[i].init);
1199 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1203 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1205 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1206 init = xstrdup (operand_type_init[i].init);
1207 process_i386_operand_type (fp, init, 1, " ", -1);
1215 /* Program options. */
1216 #define OPTION_SRCDIR 200
1218 struct option long_options[] =
1220 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1221 {"debug", no_argument, NULL, 'd'},
1222 {"version", no_argument, NULL, 'V'},
1223 {"help", no_argument, NULL, 'h'},
1224 {0, no_argument, NULL, 0}
1228 print_version (void)
1230 printf ("%s: version 1.0\n", program_name);
1235 usage (FILE * stream, int status)
1237 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1243 main (int argc, char **argv)
1245 extern int chdir (char *);
1246 char *srcdir = NULL;
1250 program_name = *argv;
1251 xmalloc_set_program_name (program_name);
1253 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1278 if (chdir (srcdir) != 0)
1279 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1280 srcdir, xstrerror (errno));
1282 /* Check the unused bitfield in i386_cpu_flags. */
1284 c = CpuNumOfBits - CpuMax - 1;
1286 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1289 /* Check the unused bitfield in i386_operand_type. */
1291 c = OTNumOfBits - OTMax - 1;
1293 fail (_("%d unused bits in i386_operand_type.\n"), c);
1296 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1299 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1300 sizeof (opcode_modifiers [0]), compare);
1302 qsort (operand_types, ARRAY_SIZE (operand_types),
1303 sizeof (operand_types [0]), compare);
1305 table = fopen ("i386-tbl.h", "w");
1307 fail (_("can't create i386-tbl.h, errno = %s\n"),
1310 process_copyright (table);
1312 process_i386_opcodes (table);
1313 process_i386_registers (table);
1314 process_i386_initializers ();