1 /* Copyright 2007, 2008 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),
276 BITFIELD (CheckSize),
284 BITFIELD (RegKludge),
285 BITFIELD (FirstXmm0),
286 BITFIELD (ByteOkIntel),
289 BITFIELD (AddrPrefixOp0),
299 BITFIELD (ATTMnemonic),
300 BITFIELD (ATTSyntax),
303 static bitfield operand_types[] =
319 BITFIELD (BaseIndex),
325 BITFIELD (InOutPortReg),
326 BITFIELD (ShiftCount),
334 BITFIELD (JumpAbsolute),
343 static const char *filename;
346 compare (const void *x, const void *y)
348 const bitfield *xp = (const bitfield *) x;
349 const bitfield *yp = (const bitfield *) y;
350 return xp->position - yp->position;
354 fail (const char *message, ...)
358 va_start (args, message);
359 fprintf (stderr, _("%s: Error: "), program_name);
360 vfprintf (stderr, message, args);
366 process_copyright (FILE *fp)
368 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
369 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
371 This file is part of the GNU opcodes library.\n\
373 This library is free software; you can redistribute it and/or modify\n\
374 it under the terms of the GNU General Public License as published by\n\
375 the Free Software Foundation; either version 3, or (at your option)\n\
376 any later version.\n\
378 It is distributed in the hope that it will be useful, but WITHOUT\n\
379 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
380 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
381 License for more details.\n\
383 You should have received a copy of the GNU General Public License\n\
384 along with this program; if not, write to the Free Software\n\
385 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
386 MA 02110-1301, USA. */\n");
389 /* Remove leading white spaces. */
392 remove_leading_whitespaces (char *str)
394 while (ISSPACE (*str))
399 /* Remove trailing white spaces. */
402 remove_trailing_whitespaces (char *str)
404 size_t last = strlen (str);
412 if (ISSPACE (str [last]))
420 /* Find next field separated by SEP and terminate it. Return a
421 pointer to the one after it. */
424 next_field (char *str, char sep, char **next)
428 p = remove_leading_whitespaces (str);
429 for (str = p; *str != sep && *str != '\0'; str++);
432 remove_trailing_whitespaces (p);
440 set_bitfield (const char *f, bitfield *array, unsigned int size)
444 if (strcmp (f, "CpuSledgehammer") == 0)
447 for (i = 0; i < size; i++)
448 if (strcasecmp (array[i].name, f) == 0)
454 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
458 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
459 int macro, const char *comma, const char *indent)
463 fprintf (table, "%s{ { ", indent);
465 for (i = 0; i < size - 1; i++)
467 fprintf (table, "%d, ", flags[i].value);
468 if (((i + 1) % 20) == 0)
470 /* We need \\ for macro. */
472 fprintf (table, " \\\n %s", indent);
474 fprintf (table, "\n %s", indent);
478 fprintf (table, "%d } }%s\n", flags[i].value, comma);
482 process_i386_cpu_flag (FILE *table, char *flag, int macro,
483 const char *comma, const char *indent)
485 char *str, *next, *last;
486 bitfield flags [ARRAY_SIZE (cpu_flags)];
488 /* Copy the default cpu flags. */
489 memcpy (flags, cpu_flags, sizeof (cpu_flags));
491 if (strcasecmp (flag, "unknown") == 0)
495 /* We turn on everything except for cpu64 in case of
496 CPU_UNKNOWN_FLAGS. */
497 for (i = 0; i < ARRAY_SIZE (flags); i++)
498 if (flags[i].position != Cpu64)
501 else if (strcmp (flag, "0"))
503 last = flag + strlen (flag);
504 for (next = flag; next && next < last; )
506 str = next_field (next, '|', &next);
508 set_bitfield (str, flags, ARRAY_SIZE (flags));
512 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
517 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
521 fprintf (table, " { ");
523 for (i = 0; i < size - 1; i++)
525 fprintf (table, "%d, ", modifier[i].value);
526 if (((i + 1) % 20) == 0)
527 fprintf (table, "\n ");
530 fprintf (table, "%d },\n", modifier[i].value);
534 process_i386_opcode_modifier (FILE *table, char *mod)
536 char *str, *next, *last;
537 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
539 /* Copy the default opcode modifier. */
540 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
542 if (strcmp (mod, "0"))
544 last = mod + strlen (mod);
545 for (next = mod; next && next < last; )
547 str = next_field (next, '|', &next);
549 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
552 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
556 output_operand_type (FILE *table, bitfield *types, unsigned int size,
557 int macro, const char *indent)
561 fprintf (table, "{ { ");
563 for (i = 0; i < size - 1; i++)
565 fprintf (table, "%d, ", types[i].value);
566 if (((i + 1) % 20) == 0)
568 /* We need \\ for macro. */
570 fprintf (table, "\\\n%s", indent);
572 fprintf (table, "\n%s", indent);
576 fprintf (table, "%d } }", types[i].value);
580 process_i386_operand_type (FILE *table, char *op, int macro,
583 char *str, *next, *last;
584 bitfield types [ARRAY_SIZE (operand_types)];
586 /* Copy the default operand type. */
587 memcpy (types, operand_types, sizeof (types));
589 if (strcmp (op, "0"))
591 last = op + strlen (op);
592 for (next = op; next && next < last; )
594 str = next_field (next, '|', &next);
596 set_bitfield (str, types, ARRAY_SIZE (types));
599 output_operand_type (table, types, ARRAY_SIZE (types), macro,
604 process_i386_opcodes (FILE *table)
609 char *str, *p, *last;
610 char *name, *operands, *base_opcode, *extension_opcode;
612 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
614 filename = "i386-opc.tbl";
615 fp = fopen (filename, "r");
618 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
621 fprintf (table, "\n/* i386 opcode table. */\n\n");
622 fprintf (table, "const template i386_optab[] =\n{\n");
626 if (fgets (buf, sizeof (buf), fp) == NULL)
631 p = remove_leading_whitespaces (buf);
634 str = strstr (p, "//");
638 /* Remove trailing white spaces. */
639 remove_trailing_whitespaces (p);
644 fprintf (table, "%s\n", p);
652 last = p + strlen (p);
655 name = next_field (p, ',', &str);
660 /* Find number of operands. */
661 operands = next_field (str, ',', &str);
666 /* Find base_opcode. */
667 base_opcode = next_field (str, ',', &str);
672 /* Find extension_opcode. */
673 extension_opcode = next_field (str, ',', &str);
678 /* Find opcode_length. */
679 opcode_length = next_field (str, ',', &str);
684 /* Find cpu_flags. */
685 cpu_flags = next_field (str, ',', &str);
690 /* Find opcode_modifier. */
691 opcode_modifier = next_field (str, ',', &str);
696 /* Remove the first {. */
697 str = remove_leading_whitespaces (str);
700 str = remove_leading_whitespaces (str + 1);
704 /* There are at least "X}". */
708 /* Remove trailing white spaces and }. */
712 if (ISSPACE (str[i]) || str[i] == '}')
721 /* Find operand_types. */
722 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
726 operand_types [i] = NULL;
730 operand_types [i] = next_field (str, ',', &str);
731 if (*operand_types[i] == '0')
734 operand_types[i] = NULL;
739 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
740 name, operands, base_opcode, extension_opcode,
743 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
745 process_i386_opcode_modifier (table, opcode_modifier);
747 fprintf (table, " { ");
749 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
751 if (operand_types[i] == NULL
752 || *operand_types[i] == '0')
755 process_i386_operand_type (table, "0", 0, "\t ");
760 fprintf (table, ",\n ");
762 process_i386_operand_type (table, operand_types[i], 0,
765 fprintf (table, " } },\n");
770 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
772 process_i386_cpu_flag (table, "0", 0, ",", " ");
774 process_i386_opcode_modifier (table, "0");
776 fprintf (table, " { ");
777 process_i386_operand_type (table, "0", 0, "\t ");
778 fprintf (table, " } }\n");
780 fprintf (table, "};\n");
784 process_i386_registers (FILE *table)
788 char *str, *p, *last;
789 char *reg_name, *reg_type, *reg_flags, *reg_num;
791 filename = "i386-reg.tbl";
792 fp = fopen (filename, "r");
794 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
797 fprintf (table, "\n/* i386 register table. */\n\n");
798 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
802 if (fgets (buf, sizeof (buf), fp) == NULL)
807 p = remove_leading_whitespaces (buf);
810 str = strstr (p, "//");
814 /* Remove trailing white spaces. */
815 remove_trailing_whitespaces (p);
820 fprintf (table, "%s\n", p);
828 last = p + strlen (p);
831 reg_name = next_field (p, ',', &str);
837 reg_type = next_field (str, ',', &str);
842 /* Find reg_flags. */
843 reg_flags = next_field (str, ',', &str);
849 reg_num = next_field (str, ',', &str);
851 fprintf (table, " { \"%s\",\n ", reg_name);
853 process_i386_operand_type (table, reg_type, 0, "\t");
855 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
860 fprintf (table, "};\n");
862 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
866 process_i386_initializers (void)
869 FILE *fp = fopen ("i386-init.h", "w");
873 fail (_("can't create i386-init.h, errno = %s\n"),
876 process_copyright (fp);
878 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
880 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
881 init = xstrdup (cpu_flag_init[i].init);
882 process_i386_cpu_flag (fp, init, 1, "", " ");
886 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
888 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
889 init = xstrdup (operand_type_init[i].init);
890 process_i386_operand_type (fp, init, 1, " ");
898 /* Program options. */
899 #define OPTION_SRCDIR 200
901 struct option long_options[] =
903 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
904 {"debug", no_argument, NULL, 'd'},
905 {"version", no_argument, NULL, 'V'},
906 {"help", no_argument, NULL, 'h'},
907 {0, no_argument, NULL, 0}
913 printf ("%s: version 1.0\n", program_name);
918 usage (FILE * stream, int status)
920 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
926 main (int argc, char **argv)
928 extern int chdir (char *);
933 program_name = *argv;
934 xmalloc_set_program_name (program_name);
936 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
961 if (chdir (srcdir) != 0)
962 fail (_("unable to change directory to \"%s\", errno = %s\n"),
963 srcdir, xstrerror (errno));
965 /* Check the unused bitfield in i386_cpu_flags. */
967 c = CpuNumOfBits - CpuMax - 1;
969 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
972 /* Check the unused bitfield in i386_operand_type. */
974 c = OTNumOfBits - OTMax - 1;
976 fail (_("%d unused bits in i386_operand_type.\n"), c);
979 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
982 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
983 sizeof (opcode_modifiers [0]), compare);
985 qsort (operand_types, ARRAY_SIZE (operand_types),
986 sizeof (operand_types [0]), compare);
988 table = fopen ("i386-tbl.h", "w");
990 fail (_("can't create i386-tbl.h, errno = %s\n"),
993 process_copyright (table);
995 process_i386_opcodes (table);
996 process_i386_registers (table);
997 process_i386_initializers ();