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|CpuSSE|CpuSSE2|CpuLM" },
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|CpuSSE" },
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2" },
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|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|Cpu3dnow|Cpu3dnowA" },
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
83 { "CPU_AMDFAM10_FLAGS",
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
90 "CpuMMX|CpuSSE|CpuSSE2" },
92 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
94 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
96 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
98 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
106 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
107 { "CPU_PCLMUL_FLAGS",
108 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
110 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
117 { "CPU_3DNOWA_FLAGS",
118 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
119 { "CPU_PADLOCK_FLAGS",
124 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
128 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
130 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
133 static initializer operand_type_init
[] =
135 { "OPERAND_TYPE_NONE",
137 { "OPERAND_TYPE_REG8",
139 { "OPERAND_TYPE_REG16",
141 { "OPERAND_TYPE_REG32",
143 { "OPERAND_TYPE_REG64",
145 { "OPERAND_TYPE_IMM1",
147 { "OPERAND_TYPE_IMM8",
149 { "OPERAND_TYPE_IMM8S",
151 { "OPERAND_TYPE_IMM16",
153 { "OPERAND_TYPE_IMM32",
155 { "OPERAND_TYPE_IMM32S",
157 { "OPERAND_TYPE_IMM64",
159 { "OPERAND_TYPE_BASEINDEX",
161 { "OPERAND_TYPE_DISP8",
163 { "OPERAND_TYPE_DISP16",
165 { "OPERAND_TYPE_DISP32",
167 { "OPERAND_TYPE_DISP32S",
169 { "OPERAND_TYPE_DISP64",
171 { "OPERAND_TYPE_INOUTPORTREG",
173 { "OPERAND_TYPE_SHIFTCOUNT",
175 { "OPERAND_TYPE_CONTROL",
177 { "OPERAND_TYPE_TEST",
179 { "OPERAND_TYPE_DEBUG",
181 { "OPERAND_TYPE_FLOATREG",
183 { "OPERAND_TYPE_FLOATACC",
185 { "OPERAND_TYPE_SREG2",
187 { "OPERAND_TYPE_SREG3",
189 { "OPERAND_TYPE_ACC",
191 { "OPERAND_TYPE_JUMPABSOLUTE",
193 { "OPERAND_TYPE_REGMMX",
195 { "OPERAND_TYPE_REGXMM",
197 { "OPERAND_TYPE_REGYMM",
199 { "OPERAND_TYPE_ESSEG",
201 { "OPERAND_TYPE_ACC32",
203 { "OPERAND_TYPE_ACC64",
205 { "OPERAND_TYPE_INOUTPORTREG",
207 { "OPERAND_TYPE_REG16_INOUTPORTREG",
208 "Reg16|InOutPortReg" },
209 { "OPERAND_TYPE_DISP16_32",
211 { "OPERAND_TYPE_ANYDISP",
212 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
213 { "OPERAND_TYPE_IMM16_32",
215 { "OPERAND_TYPE_IMM16_32S",
217 { "OPERAND_TYPE_IMM16_32_32S",
218 "Imm16|Imm32|Imm32S" },
219 { "OPERAND_TYPE_IMM32_32S_DISP32",
220 "Imm32|Imm32S|Disp32" },
221 { "OPERAND_TYPE_IMM64_DISP64",
223 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
224 "Imm32|Imm32S|Imm64|Disp32" },
225 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
226 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
227 { "OPERAND_TYPE_VEX_IMM4",
231 typedef struct bitfield
238 #define BITFIELD(n) { n, 0, #n }
240 static bitfield cpu_flags
[] =
256 BITFIELD (CpuSSE4_1
),
257 BITFIELD (CpuSSE4_2
),
262 BITFIELD (Cpu3dnowA
),
263 BITFIELD (CpuPadLock
),
270 BITFIELD (CpuPCLMUL
),
278 BITFIELD (CpuUnused
),
282 static bitfield opcode_modifiers
[] =
287 BITFIELD (ShortForm
),
289 BITFIELD (JumpDword
),
291 BITFIELD (JumpInterSegment
),
298 BITFIELD (IgnoreSize
),
299 BITFIELD (DefaultSize
),
308 BITFIELD (RegKludge
),
309 BITFIELD (FirstXmm0
),
310 BITFIELD (Implicit1stXmm0
),
311 BITFIELD (ByteOkIntel
),
314 BITFIELD (AddrPrefixOp0
),
332 BITFIELD (Vex3Sources
),
333 BITFIELD (VexImmExt
),
337 BITFIELD (ATTMnemonic
),
338 BITFIELD (ATTSyntax
),
339 BITFIELD (IntelSyntax
),
342 static bitfield operand_types
[] =
359 BITFIELD (BaseIndex
),
365 BITFIELD (InOutPortReg
),
366 BITFIELD (ShiftCount
),
374 BITFIELD (JumpAbsolute
),
386 BITFIELD (Unspecified
),
395 static const char *filename
;
398 compare (const void *x
, const void *y
)
400 const bitfield
*xp
= (const bitfield
*) x
;
401 const bitfield
*yp
= (const bitfield
*) y
;
402 return xp
->position
- yp
->position
;
406 fail (const char *message
, ...)
410 va_start (args
, message
);
411 fprintf (stderr
, _("%s: Error: "), program_name
);
412 vfprintf (stderr
, message
, args
);
418 process_copyright (FILE *fp
)
420 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
421 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
423 This file is part of the GNU opcodes library.\n\
425 This library is free software; you can redistribute it and/or modify\n\
426 it under the terms of the GNU General Public License as published by\n\
427 the Free Software Foundation; either version 3, or (at your option)\n\
428 any later version.\n\
430 It is distributed in the hope that it will be useful, but WITHOUT\n\
431 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
432 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
433 License for more details.\n\
435 You should have received a copy of the GNU General Public License\n\
436 along with this program; if not, write to the Free Software\n\
437 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
438 MA 02110-1301, USA. */\n");
441 /* Remove leading white spaces. */
444 remove_leading_whitespaces (char *str
)
446 while (ISSPACE (*str
))
451 /* Remove trailing white spaces. */
454 remove_trailing_whitespaces (char *str
)
456 size_t last
= strlen (str
);
464 if (ISSPACE (str
[last
]))
472 /* Find next field separated by SEP and terminate it. Return a
473 pointer to the one after it. */
476 next_field (char *str
, char sep
, char **next
)
480 p
= remove_leading_whitespaces (str
);
481 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
484 remove_trailing_whitespaces (p
);
492 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
496 if (strcmp (f
, "CpuSledgehammer") == 0)
498 else if (strcmp (f
, "Mmword") == 0)
500 else if (strcmp (f
, "Oword") == 0)
503 for (i
= 0; i
< size
; i
++)
504 if (strcasecmp (array
[i
].name
, f
) == 0)
510 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
514 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
515 int macro
, const char *comma
, const char *indent
)
519 fprintf (table
, "%s{ { ", indent
);
521 for (i
= 0; i
< size
- 1; i
++)
523 fprintf (table
, "%d, ", flags
[i
].value
);
524 if (((i
+ 1) % 20) == 0)
526 /* We need \\ for macro. */
528 fprintf (table
, " \\\n %s", indent
);
530 fprintf (table
, "\n %s", indent
);
534 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
538 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
539 const char *comma
, const char *indent
)
541 char *str
, *next
, *last
;
542 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
544 /* Copy the default cpu flags. */
545 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
547 if (strcasecmp (flag
, "unknown") == 0)
551 /* We turn on everything except for cpu64 in case of
552 CPU_UNKNOWN_FLAGS. */
553 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
554 if (flags
[i
].position
!= Cpu64
)
557 else if (strcmp (flag
, "0"))
559 last
= flag
+ strlen (flag
);
560 for (next
= flag
; next
&& next
< last
; )
562 str
= next_field (next
, '|', &next
);
564 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
568 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
573 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
577 fprintf (table
, " { ");
579 for (i
= 0; i
< size
- 1; i
++)
581 fprintf (table
, "%d, ", modifier
[i
].value
);
582 if (((i
+ 1) % 20) == 0)
583 fprintf (table
, "\n ");
586 fprintf (table
, "%d },\n", modifier
[i
].value
);
590 process_i386_opcode_modifier (FILE *table
, char *mod
)
592 char *str
, *next
, *last
;
593 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
595 /* Copy the default opcode modifier. */
596 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
598 if (strcmp (mod
, "0"))
600 last
= mod
+ strlen (mod
);
601 for (next
= mod
; next
&& next
< last
; )
603 str
= next_field (next
, '|', &next
);
605 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
608 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
612 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
613 int macro
, const char *indent
)
617 fprintf (table
, "{ { ");
619 for (i
= 0; i
< size
- 1; i
++)
621 fprintf (table
, "%d, ", types
[i
].value
);
622 if (((i
+ 1) % 20) == 0)
624 /* We need \\ for macro. */
626 fprintf (table
, "\\\n%s", indent
);
628 fprintf (table
, "\n%s", indent
);
632 fprintf (table
, "%d } }", types
[i
].value
);
636 process_i386_operand_type (FILE *table
, char *op
, int macro
,
639 char *str
, *next
, *last
;
640 bitfield types
[ARRAY_SIZE (operand_types
)];
642 /* Copy the default operand type. */
643 memcpy (types
, operand_types
, sizeof (types
));
645 if (strcmp (op
, "0"))
647 last
= op
+ strlen (op
);
648 for (next
= op
; next
&& next
< last
; )
650 str
= next_field (next
, '|', &next
);
652 set_bitfield (str
, types
, ARRAY_SIZE (types
));
655 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
660 process_i386_opcodes (FILE *table
)
665 char *str
, *p
, *last
;
666 char *name
, *operands
, *base_opcode
, *extension_opcode
;
668 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
670 filename
= "i386-opc.tbl";
671 fp
= fopen (filename
, "r");
674 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
677 fprintf (table
, "\n/* i386 opcode table. */\n\n");
678 fprintf (table
, "const template i386_optab[] =\n{\n");
682 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
687 p
= remove_leading_whitespaces (buf
);
690 str
= strstr (p
, "//");
694 /* Remove trailing white spaces. */
695 remove_trailing_whitespaces (p
);
700 fprintf (table
, "%s\n", p
);
708 last
= p
+ strlen (p
);
711 name
= next_field (p
, ',', &str
);
716 /* Find number of operands. */
717 operands
= next_field (str
, ',', &str
);
722 /* Find base_opcode. */
723 base_opcode
= next_field (str
, ',', &str
);
728 /* Find extension_opcode. */
729 extension_opcode
= next_field (str
, ',', &str
);
734 /* Find opcode_length. */
735 opcode_length
= next_field (str
, ',', &str
);
740 /* Find cpu_flags. */
741 cpu_flags
= next_field (str
, ',', &str
);
746 /* Find opcode_modifier. */
747 opcode_modifier
= next_field (str
, ',', &str
);
752 /* Remove the first {. */
753 str
= remove_leading_whitespaces (str
);
756 str
= remove_leading_whitespaces (str
+ 1);
760 /* There are at least "X}". */
764 /* Remove trailing white spaces and }. */
768 if (ISSPACE (str
[i
]) || str
[i
] == '}')
777 /* Find operand_types. */
778 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
782 operand_types
[i
] = NULL
;
786 operand_types
[i
] = next_field (str
, ',', &str
);
787 if (*operand_types
[i
] == '0')
790 operand_types
[i
] = NULL
;
795 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
796 name
, operands
, base_opcode
, extension_opcode
,
799 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
801 process_i386_opcode_modifier (table
, opcode_modifier
);
803 fprintf (table
, " { ");
805 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
807 if (operand_types
[i
] == NULL
808 || *operand_types
[i
] == '0')
811 process_i386_operand_type (table
, "0", 0, "\t ");
816 fprintf (table
, ",\n ");
818 process_i386_operand_type (table
, operand_types
[i
], 0,
821 fprintf (table
, " } },\n");
826 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
828 process_i386_cpu_flag (table
, "0", 0, ",", " ");
830 process_i386_opcode_modifier (table
, "0");
832 fprintf (table
, " { ");
833 process_i386_operand_type (table
, "0", 0, "\t ");
834 fprintf (table
, " } }\n");
836 fprintf (table
, "};\n");
840 process_i386_registers (FILE *table
)
844 char *str
, *p
, *last
;
845 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
846 char *dw2_32_num
, *dw2_64_num
;
848 filename
= "i386-reg.tbl";
849 fp
= fopen (filename
, "r");
851 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
854 fprintf (table
, "\n/* i386 register table. */\n\n");
855 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
859 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
864 p
= remove_leading_whitespaces (buf
);
867 str
= strstr (p
, "//");
871 /* Remove trailing white spaces. */
872 remove_trailing_whitespaces (p
);
877 fprintf (table
, "%s\n", p
);
885 last
= p
+ strlen (p
);
888 reg_name
= next_field (p
, ',', &str
);
894 reg_type
= next_field (str
, ',', &str
);
899 /* Find reg_flags. */
900 reg_flags
= next_field (str
, ',', &str
);
906 reg_num
= next_field (str
, ',', &str
);
911 fprintf (table
, " { \"%s\",\n ", reg_name
);
913 process_i386_operand_type (table
, reg_type
, 0, "\t");
915 /* Find 32-bit Dwarf2 register number. */
916 dw2_32_num
= next_field (str
, ',', &str
);
921 /* Find 64-bit Dwarf2 register number. */
922 dw2_64_num
= next_field (str
, ',', &str
);
924 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
925 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
930 fprintf (table
, "};\n");
932 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
936 process_i386_initializers (void)
939 FILE *fp
= fopen ("i386-init.h", "w");
943 fail (_("can't create i386-init.h, errno = %s\n"),
946 process_copyright (fp
);
948 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
950 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
951 init
= xstrdup (cpu_flag_init
[i
].init
);
952 process_i386_cpu_flag (fp
, init
, 1, "", " ");
956 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
958 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
959 init
= xstrdup (operand_type_init
[i
].init
);
960 process_i386_operand_type (fp
, init
, 1, " ");
968 /* Program options. */
969 #define OPTION_SRCDIR 200
971 struct option long_options
[] =
973 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
974 {"debug", no_argument
, NULL
, 'd'},
975 {"version", no_argument
, NULL
, 'V'},
976 {"help", no_argument
, NULL
, 'h'},
977 {0, no_argument
, NULL
, 0}
983 printf ("%s: version 1.0\n", program_name
);
988 usage (FILE * stream
, int status
)
990 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
996 main (int argc
, char **argv
)
998 extern int chdir (char *);
1003 program_name
= *argv
;
1004 xmalloc_set_program_name (program_name
);
1006 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1031 if (chdir (srcdir
) != 0)
1032 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1033 srcdir
, xstrerror (errno
));
1035 /* Check the unused bitfield in i386_cpu_flags. */
1037 c
= CpuNumOfBits
- CpuMax
- 1;
1039 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1042 /* Check the unused bitfield in i386_operand_type. */
1044 c
= OTNumOfBits
- OTMax
- 1;
1046 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1049 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1052 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1053 sizeof (opcode_modifiers
[0]), compare
);
1055 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1056 sizeof (operand_types
[0]), compare
);
1058 table
= fopen ("i386-tbl.h", "w");
1060 fail (_("can't create i386-tbl.h, errno = %s\n"),
1063 process_copyright (table
);
1065 process_i386_opcodes (table
);
1066 process_i386_registers (table
);
1067 process_i386_initializers ();