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 ();