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),
248 BITFIELD (CpuUnused),
252 static bitfield opcode_modifiers[] =
257 BITFIELD (ShortForm),
259 BITFIELD (JumpDword),
261 BITFIELD (JumpInterSegment),
268 BITFIELD (IgnoreSize),
269 BITFIELD (DefaultSize),
278 BITFIELD (RegKludge),
289 static bitfield operand_types[] =
305 BITFIELD (BaseIndex),
311 BITFIELD (InOutPortReg),
312 BITFIELD (ShiftCount),
320 BITFIELD (JumpAbsolute),
329 compare (const void *x, const void *y)
331 const bitfield *xp = (const bitfield *) x;
332 const bitfield *yp = (const bitfield *) y;
333 return xp->position - yp->position;
337 fail (const char *message, ...)
341 va_start (args, message);
342 fprintf (stderr, _("%s: Error: "), program_name);
343 vfprintf (stderr, message, args);
349 process_copyright (FILE *fp)
351 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
352 /* Copyright 2007 Free Software Foundation, Inc.\n\
354 This file is part of the GNU opcodes library.\n\
356 This library is free software; you can redistribute it and/or modify\n\
357 it under the terms of the GNU General Public License as published by\n\
358 the Free Software Foundation; either version 3, or (at your option)\n\
359 any later version.\n\
361 It is distributed in the hope that it will be useful, but WITHOUT\n\
362 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
363 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
364 License for more details.\n\
366 You should have received a copy of the GNU General Public License\n\
367 along with this program; if not, write to the Free Software\n\
368 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
369 MA 02110-1301, USA. */\n");
372 /* Remove leading white spaces. */
375 remove_leading_whitespaces (char *str)
377 while (ISSPACE (*str))
382 /* Remove trailing white spaces. */
385 remove_trailing_whitespaces (char *str)
387 size_t last = strlen (str);
395 if (ISSPACE (str [last]))
403 /* Find next field separated by SEP and terminate it. Return a
404 pointer to the one after it. */
407 next_field (char *str, char sep, char **next)
411 p = remove_leading_whitespaces (str);
412 for (str = p; *str != sep && *str != '\0'; str++);
415 remove_trailing_whitespaces (p);
423 set_bitfield (const char *f, bitfield *array, unsigned int size)
427 if (strcmp (f, "CpuSledgehammer") == 0)
430 for (i = 0; i < size; i++)
431 if (strcasecmp (array[i].name, f) == 0)
437 printf ("Unknown bitfield: %s\n", f);
442 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
443 int macro, const char *comma, const char *indent)
447 fprintf (table, "%s{ { ", indent);
449 for (i = 0; i < size - 1; i++)
451 fprintf (table, "%d, ", flags[i].value);
452 if (((i + 1) % 20) == 0)
454 /* We need \\ for macro. */
456 fprintf (table, " \\\n %s", indent);
458 fprintf (table, "\n %s", indent);
462 fprintf (table, "%d } }%s\n", flags[i].value, comma);
466 process_i386_cpu_flag (FILE *table, char *flag, int macro,
467 const char *comma, const char *indent)
469 char *str, *next, *last;
470 bitfield flags [ARRAY_SIZE (cpu_flags)];
472 /* Copy the default cpu flags. */
473 memcpy (flags, cpu_flags, sizeof (cpu_flags));
475 if (strcasecmp (flag, "unknown") == 0)
479 /* We turn on everything except for cpu64 in case of
480 CPU_UNKNOWN_FLAGS. */
481 for (i = 0; i < ARRAY_SIZE (flags); i++)
482 if (flags[i].position != Cpu64)
485 else if (strcmp (flag, "0"))
487 last = flag + strlen (flag);
488 for (next = flag; next && next < last; )
490 str = next_field (next, '|', &next);
492 set_bitfield (str, flags, ARRAY_SIZE (flags));
496 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
501 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
505 fprintf (table, " { ");
507 for (i = 0; i < size - 1; i++)
509 fprintf (table, "%d, ", modifier[i].value);
510 if (((i + 1) % 20) == 0)
511 fprintf (table, "\n ");
514 fprintf (table, "%d },\n", modifier[i].value);
518 process_i386_opcode_modifier (FILE *table, char *mod)
520 char *str, *next, *last;
521 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
523 /* Copy the default opcode modifier. */
524 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
526 if (strcmp (mod, "0"))
528 last = mod + strlen (mod);
529 for (next = mod; next && next < last; )
531 str = next_field (next, '|', &next);
533 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
536 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
540 output_operand_type (FILE *table, bitfield *types, unsigned int size,
541 int macro, const char *indent)
545 fprintf (table, "{ { ");
547 for (i = 0; i < size - 1; i++)
549 fprintf (table, "%d, ", types[i].value);
550 if (((i + 1) % 20) == 0)
552 /* We need \\ for macro. */
554 fprintf (table, "\\\n%s", indent);
556 fprintf (table, "\n%s", indent);
560 fprintf (table, "%d } }", types[i].value);
564 process_i386_operand_type (FILE *table, char *op, int macro,
567 char *str, *next, *last;
568 bitfield types [ARRAY_SIZE (operand_types)];
570 /* Copy the default operand type. */
571 memcpy (types, operand_types, sizeof (types));
573 if (strcmp (op, "0"))
575 last = op + strlen (op);
576 for (next = op; next && next < last; )
578 str = next_field (next, '|', &next);
580 set_bitfield (str, types, ARRAY_SIZE (types));
583 output_operand_type (table, types, ARRAY_SIZE (types), macro,
588 process_i386_opcodes (FILE *table)
590 FILE *fp = fopen ("i386-opc.tbl", "r");
593 char *str, *p, *last;
594 char *name, *operands, *base_opcode, *extension_opcode;
596 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
599 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
602 fprintf (table, "\n/* i386 opcode table. */\n\n");
603 fprintf (table, "const template i386_optab[] =\n{\n");
607 if (fgets (buf, sizeof (buf), fp) == NULL)
610 p = remove_leading_whitespaces (buf);
613 str = strstr (p, "//");
617 /* Remove trailing white spaces. */
618 remove_trailing_whitespaces (p);
623 fprintf (table, "%s\n", p);
631 last = p + strlen (p);
634 name = next_field (p, ',', &str);
639 /* Find number of operands. */
640 operands = next_field (str, ',', &str);
645 /* Find base_opcode. */
646 base_opcode = next_field (str, ',', &str);
651 /* Find extension_opcode. */
652 extension_opcode = next_field (str, ',', &str);
657 /* Find opcode_length. */
658 opcode_length = next_field (str, ',', &str);
663 /* Find cpu_flags. */
664 cpu_flags = next_field (str, ',', &str);
669 /* Find opcode_modifier. */
670 opcode_modifier = next_field (str, ',', &str);
675 /* Remove the first {. */
676 str = remove_leading_whitespaces (str);
679 str = remove_leading_whitespaces (str + 1);
683 /* There are at least "X}". */
687 /* Remove trailing white spaces and }. */
691 if (ISSPACE (str[i]) || str[i] == '}')
700 /* Find operand_types. */
701 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
705 operand_types [i] = NULL;
709 operand_types [i] = next_field (str, ',', &str);
710 if (*operand_types[i] == '0')
713 operand_types[i] = NULL;
718 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
719 name, operands, base_opcode, extension_opcode,
722 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
724 process_i386_opcode_modifier (table, opcode_modifier);
726 fprintf (table, " { ");
728 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
730 if (operand_types[i] == NULL
731 || *operand_types[i] == '0')
734 process_i386_operand_type (table, "0", 0, "\t ");
739 fprintf (table, ",\n ");
741 process_i386_operand_type (table, operand_types[i], 0,
744 fprintf (table, " } },\n");
749 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
751 process_i386_cpu_flag (table, "0", 0, ",", " ");
753 process_i386_opcode_modifier (table, "0");
755 fprintf (table, " { ");
756 process_i386_operand_type (table, "0", 0, "\t ");
757 fprintf (table, " } }\n");
759 fprintf (table, "};\n");
763 process_i386_registers (FILE *table)
765 FILE *fp = fopen ("i386-reg.tbl", "r");
767 char *str, *p, *last;
768 char *reg_name, *reg_type, *reg_flags, *reg_num;
771 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
774 fprintf (table, "\n/* i386 register table. */\n\n");
775 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
779 if (fgets (buf, sizeof (buf), fp) == NULL)
782 p = remove_leading_whitespaces (buf);
785 str = strstr (p, "//");
789 /* Remove trailing white spaces. */
790 remove_trailing_whitespaces (p);
795 fprintf (table, "%s\n", p);
803 last = p + strlen (p);
806 reg_name = next_field (p, ',', &str);
812 reg_type = next_field (str, ',', &str);
817 /* Find reg_flags. */
818 reg_flags = next_field (str, ',', &str);
824 reg_num = next_field (str, ',', &str);
826 fprintf (table, " { \"%s\",\n ", reg_name);
828 process_i386_operand_type (table, reg_type, 0, "\t");
830 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
835 fprintf (table, "};\n");
837 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
841 process_i386_initializers (void)
844 FILE *fp = fopen ("i386-init.h", "w");
848 fail (_("can't create i386-init.h, errno = %s\n"),
851 process_copyright (fp);
853 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
855 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
856 init = xstrdup (cpu_flag_init[i].init);
857 process_i386_cpu_flag (fp, init, 1, "", " ");
861 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
863 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
864 init = xstrdup (operand_type_init[i].init);
865 process_i386_operand_type (fp, init, 1, " ");
873 /* Program options. */
874 #define OPTION_SRCDIR 200
876 struct option long_options[] =
878 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
879 {"debug", no_argument, NULL, 'd'},
880 {"version", no_argument, NULL, 'V'},
881 {"help", no_argument, NULL, 'h'},
882 {0, no_argument, NULL, 0}
888 printf ("%s: version 1.0\n", program_name);
893 usage (FILE * stream, int status)
895 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
901 main (int argc, char **argv)
903 extern int chdir (char *);
908 program_name = *argv;
909 xmalloc_set_program_name (program_name);
911 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
936 if (chdir (srcdir) != 0)
937 fail (_("unable to change directory to \"%s\", errno = %s\n"),
938 srcdir, xstrerror (errno));
940 /* Check the unused bitfield in i386_cpu_flags. */
942 c = CpuNumOfBits - CpuMax - 1;
944 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
947 /* Check the unused bitfield in i386_operand_type. */
949 c = OTNumOfBits - OTMax - 1;
951 fail (_("%d unused bits in i386_operand_type.\n"), c);
954 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
957 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
958 sizeof (opcode_modifiers [0]), compare);
960 qsort (operand_types, ARRAY_SIZE (operand_types),
961 sizeof (operand_types [0]), compare);
963 table = fopen ("i386-tbl.h", "w");
965 fail (_("can't create i386-tbl.h, errno = %s\n"),
968 process_copyright (table);
970 process_i386_opcodes (table);
971 process_i386_registers (table);
972 process_i386_initializers ();