1 /* Copyright 2007 Free Software Foundation, Inc.
3 This file is part of the GNU opcodes library.
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)
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.
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. */
24 #include "libiberty.h"
25 #include "safe-ctype.h"
30 #define _(String) gettext (String)
32 static const char *program_name = NULL;
35 typedef struct initializer
41 static initializer cpu_flag_init [] =
43 { "CPU_UNKNOWN_FLAGS",
45 { "CPU_GENERIC32_FLAGS",
46 "Cpu186|Cpu286|Cpu386" },
47 { "CPU_GENERIC64_FLAGS",
48 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2" },
56 "Cpu186|Cpu286|Cpu386" },
58 "Cpu186|Cpu286|Cpu386|Cpu486" },
60 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
62 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686" },
64 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX" },
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuMMX2|CpuSSE" },
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2" },
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3" },
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX" },
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow" },
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA" },
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" },
88 "CpuMMX|CpuMMX2|CpuSSE" },
90 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2" },
92 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3" },
94 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
96 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
98 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
101 { "CPU_3DNOWA_FLAGS",
102 "CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA" },
103 { "CPU_PADLOCK_FLAGS",
108 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
112 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"}
115 static initializer operand_type_init [] =
117 { "OPERAND_TYPE_NONE",
119 { "OPERAND_TYPE_REG8",
121 { "OPERAND_TYPE_REG16",
123 { "OPERAND_TYPE_REG32",
125 { "OPERAND_TYPE_REG64",
127 { "OPERAND_TYPE_IMM1",
129 { "OPERAND_TYPE_IMM8",
131 { "OPERAND_TYPE_IMM8S",
133 { "OPERAND_TYPE_IMM16",
135 { "OPERAND_TYPE_IMM32",
137 { "OPERAND_TYPE_IMM32S",
139 { "OPERAND_TYPE_IMM64",
141 { "OPERAND_TYPE_BASEINDEX",
143 { "OPERAND_TYPE_DISP8",
145 { "OPERAND_TYPE_DISP16",
147 { "OPERAND_TYPE_DISP32",
149 { "OPERAND_TYPE_DISP32S",
151 { "OPERAND_TYPE_DISP64",
153 { "OPERAND_TYPE_INOUTPORTREG",
155 { "OPERAND_TYPE_SHIFTCOUNT",
157 { "OPERAND_TYPE_CONTROL",
159 { "OPERAND_TYPE_TEST",
161 { "OPERAND_TYPE_DEBUG",
163 { "OPERAND_TYPE_FLOATREG",
165 { "OPERAND_TYPE_FLOATACC",
167 { "OPERAND_TYPE_SREG2",
169 { "OPERAND_TYPE_SREG3",
171 { "OPERAND_TYPE_ACC",
173 { "OPERAND_TYPE_JUMPABSOLUTE",
175 { "OPERAND_TYPE_REGMMX",
177 { "OPERAND_TYPE_REGXMM",
179 { "OPERAND_TYPE_ESSEG",
181 { "OPERAND_TYPE_ACC32",
183 { "OPERAND_TYPE_ACC64",
185 { "OPERAND_TYPE_REG16_INOUTPORTREG",
186 "Reg16|InOutPortReg" },
187 { "OPERAND_TYPE_DISP16_32",
189 { "OPERAND_TYPE_ANYDISP",
190 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
191 { "OPERAND_TYPE_IMM16_32",
193 { "OPERAND_TYPE_IMM16_32S",
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",
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" },
207 typedef struct bitfield
214 #define BITFIELD(n) { n, 0, #n }
216 static bitfield cpu_flags[] =
233 BITFIELD (CpuSSE4_1),
234 BITFIELD (CpuSSE4_2),
238 BITFIELD (Cpu3dnowA),
239 BITFIELD (CpuPadLock),
247 BITFIELD (CpuUnused),
251 static bitfield opcode_modifiers[] =
256 BITFIELD (ShortForm),
258 BITFIELD (JumpDword),
260 BITFIELD (JumpInterSegment),
267 BITFIELD (IgnoreSize),
268 BITFIELD (DefaultSize),
277 BITFIELD (RegKludge),
288 static bitfield operand_types[] =
304 BITFIELD (BaseIndex),
310 BITFIELD (InOutPortReg),
311 BITFIELD (ShiftCount),
319 BITFIELD (JumpAbsolute),
328 compare (const void *x, const void *y)
330 const bitfield *xp = (const bitfield *) x;
331 const bitfield *yp = (const bitfield *) y;
332 return xp->position - yp->position;
336 fail (const char *message, ...)
340 va_start (args, message);
341 fprintf (stderr, _("%s: Error: "), program_name);
342 vfprintf (stderr, message, args);
348 process_copyright (FILE *fp)
350 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
351 /* Copyright 2007 Free Software Foundation, Inc.\n\
353 This file is part of the GNU opcodes library.\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\
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\
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");
371 /* Remove leading white spaces. */
374 remove_leading_whitespaces (char *str)
376 while (ISSPACE (*str))
381 /* Remove trailing white spaces. */
384 remove_trailing_whitespaces (char *str)
386 size_t last = strlen (str);
394 if (ISSPACE (str [last]))
402 /* Find next field separated by SEP and terminate it. Return a
403 pointer to the one after it. */
406 next_field (char *str, char sep, char **next)
410 p = remove_leading_whitespaces (str);
411 for (str = p; *str != sep && *str != '\0'; str++);
414 remove_trailing_whitespaces (p);
422 set_bitfield (const char *f, bitfield *array, unsigned int size)
426 if (strcmp (f, "CpuSledgehammer") == 0)
429 for (i = 0; i < size; i++)
430 if (strcasecmp (array[i].name, f) == 0)
436 printf ("Unknown bitfield: %s\n", f);
441 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
442 int macro, const char *comma, const char *indent)
446 fprintf (table, "%s{ { ", indent);
448 for (i = 0; i < size - 1; i++)
450 fprintf (table, "%d, ", flags[i].value);
451 if (((i + 1) % 20) == 0)
453 /* We need \\ for macro. */
455 fprintf (table, " \\\n %s", indent);
457 fprintf (table, "\n %s", indent);
461 fprintf (table, "%d } }%s\n", flags[i].value, comma);
465 process_i386_cpu_flag (FILE *table, char *flag, int macro,
466 const char *comma, const char *indent)
468 char *str, *next, *last;
469 bitfield flags [ARRAY_SIZE (cpu_flags)];
471 /* Copy the default cpu flags. */
472 memcpy (flags, cpu_flags, sizeof (cpu_flags));
474 if (strcasecmp (flag, "unknown") == 0)
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)
484 else if (strcmp (flag, "0"))
486 last = flag + strlen (flag);
487 for (next = flag; next && next < last; )
489 str = next_field (next, '|', &next);
491 set_bitfield (str, flags, ARRAY_SIZE (flags));
495 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
500 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
504 fprintf (table, " { ");
506 for (i = 0; i < size - 1; i++)
508 fprintf (table, "%d, ", modifier[i].value);
509 if (((i + 1) % 20) == 0)
510 fprintf (table, "\n ");
513 fprintf (table, "%d },\n", modifier[i].value);
517 process_i386_opcode_modifier (FILE *table, char *mod)
519 char *str, *next, *last;
520 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
522 /* Copy the default opcode modifier. */
523 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
525 if (strcmp (mod, "0"))
527 last = mod + strlen (mod);
528 for (next = mod; next && next < last; )
530 str = next_field (next, '|', &next);
532 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
535 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
539 output_operand_type (FILE *table, bitfield *types, unsigned int size,
540 int macro, const char *indent)
544 fprintf (table, "{ { ");
546 for (i = 0; i < size - 1; i++)
548 fprintf (table, "%d, ", types[i].value);
549 if (((i + 1) % 20) == 0)
551 /* We need \\ for macro. */
553 fprintf (table, "\\\n%s", indent);
555 fprintf (table, "\n%s", indent);
559 fprintf (table, "%d } }", types[i].value);
563 process_i386_operand_type (FILE *table, char *op, int macro,
566 char *str, *next, *last;
567 bitfield types [ARRAY_SIZE (operand_types)];
569 /* Copy the default operand type. */
570 memcpy (types, operand_types, sizeof (types));
572 if (strcmp (op, "0"))
574 last = op + strlen (op);
575 for (next = op; next && next < last; )
577 str = next_field (next, '|', &next);
579 set_bitfield (str, types, ARRAY_SIZE (types));
582 output_operand_type (table, types, ARRAY_SIZE (types), macro,
587 process_i386_opcodes (FILE *table)
589 FILE *fp = fopen ("i386-opc.tbl", "r");
592 char *str, *p, *last;
593 char *name, *operands, *base_opcode, *extension_opcode;
595 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
598 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
601 fprintf (table, "\n/* i386 opcode table. */\n\n");
602 fprintf (table, "const template i386_optab[] =\n{\n");
606 if (fgets (buf, sizeof (buf), fp) == NULL)
609 p = remove_leading_whitespaces (buf);
612 str = strstr (p, "//");
616 /* Remove trailing white spaces. */
617 remove_trailing_whitespaces (p);
622 fprintf (table, "%s\n", p);
630 last = p + strlen (p);
633 name = next_field (p, ',', &str);
638 /* Find number of operands. */
639 operands = next_field (str, ',', &str);
644 /* Find base_opcode. */
645 base_opcode = next_field (str, ',', &str);
650 /* Find extension_opcode. */
651 extension_opcode = next_field (str, ',', &str);
656 /* Find opcode_length. */
657 opcode_length = next_field (str, ',', &str);
662 /* Find cpu_flags. */
663 cpu_flags = next_field (str, ',', &str);
668 /* Find opcode_modifier. */
669 opcode_modifier = next_field (str, ',', &str);
674 /* Remove the first {. */
675 str = remove_leading_whitespaces (str);
678 str = remove_leading_whitespaces (str + 1);
682 /* There are at least "X}". */
686 /* Remove trailing white spaces and }. */
690 if (ISSPACE (str[i]) || str[i] == '}')
699 /* Find operand_types. */
700 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
704 operand_types [i] = NULL;
708 operand_types [i] = next_field (str, ',', &str);
709 if (*operand_types[i] == '0')
712 operand_types[i] = NULL;
717 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
718 name, operands, base_opcode, extension_opcode,
721 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
723 process_i386_opcode_modifier (table, opcode_modifier);
725 fprintf (table, " { ");
727 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
729 if (operand_types[i] == NULL
730 || *operand_types[i] == '0')
733 process_i386_operand_type (table, "0", 0, "\t ");
738 fprintf (table, ",\n ");
740 process_i386_operand_type (table, operand_types[i], 0,
743 fprintf (table, " } },\n");
748 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
750 process_i386_cpu_flag (table, "0", 0, ",", " ");
752 process_i386_opcode_modifier (table, "0");
754 fprintf (table, " { ");
755 process_i386_operand_type (table, "0", 0, "\t ");
756 fprintf (table, " } }\n");
758 fprintf (table, "};\n");
762 process_i386_registers (FILE *table)
764 FILE *fp = fopen ("i386-reg.tbl", "r");
766 char *str, *p, *last;
767 char *reg_name, *reg_type, *reg_flags, *reg_num;
770 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
773 fprintf (table, "\n/* i386 register table. */\n\n");
774 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
778 if (fgets (buf, sizeof (buf), fp) == NULL)
781 p = remove_leading_whitespaces (buf);
784 str = strstr (p, "//");
788 /* Remove trailing white spaces. */
789 remove_trailing_whitespaces (p);
794 fprintf (table, "%s\n", p);
802 last = p + strlen (p);
805 reg_name = next_field (p, ',', &str);
811 reg_type = next_field (str, ',', &str);
816 /* Find reg_flags. */
817 reg_flags = next_field (str, ',', &str);
823 reg_num = next_field (str, ',', &str);
825 fprintf (table, " { \"%s\",\n ", reg_name);
827 process_i386_operand_type (table, reg_type, 0, "\t");
829 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
834 fprintf (table, "};\n");
836 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
840 process_i386_initializers (void)
843 FILE *fp = fopen ("i386-init.h", "w");
847 fail (_("can't create i386-init.h, errno = %s\n"),
850 process_copyright (fp);
852 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
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, "", " ");
860 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
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, " ");
872 /* Program options. */
873 #define OPTION_SRCDIR 200
875 struct option long_options[] =
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}
887 printf ("%s: version 1.0\n", program_name);
892 usage (FILE * stream, int status)
894 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
900 main (int argc, char **argv)
902 extern int chdir (char *);
907 program_name = *argv;
908 xmalloc_set_program_name (program_name);
910 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
935 if (chdir (srcdir) != 0)
936 fail (_("unable to change directory to \"%s\", errno = %s\n"),
937 srcdir, xstrerror (errno));
939 /* Check the unused bitfield in i386_cpu_flags. */
941 c = CpuNumOfBits - CpuMax - 1;
943 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
946 /* Check the unused bitfield in i386_operand_type. */
948 c = OTNumOfBits - OTMax - 1;
950 fail (_("%d unused bits in i386_operand_type.\n"), c);
953 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
956 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
957 sizeof (opcode_modifiers [0]), compare);
959 qsort (operand_types, ARRAY_SIZE (operand_types),
960 sizeof (operand_types [0]), compare);
962 table = fopen ("i386-tbl.h", "w");
964 fail (_("can't create i386-tbl.h, errno = %s\n"),
967 process_copyright (table);
969 process_i386_opcodes (table);
970 process_i386_registers (table);
971 process_i386_initializers ();