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" },
113 { "CPU_3DNOWA_FLAGS",
114 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
115 { "CPU_PADLOCK_FLAGS",
120 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
124 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
126 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
129 static initializer operand_type_init
[] =
131 { "OPERAND_TYPE_NONE",
133 { "OPERAND_TYPE_REG8",
135 { "OPERAND_TYPE_REG16",
137 { "OPERAND_TYPE_REG32",
139 { "OPERAND_TYPE_REG64",
141 { "OPERAND_TYPE_IMM1",
143 { "OPERAND_TYPE_IMM8",
145 { "OPERAND_TYPE_IMM8S",
147 { "OPERAND_TYPE_IMM16",
149 { "OPERAND_TYPE_IMM32",
151 { "OPERAND_TYPE_IMM32S",
153 { "OPERAND_TYPE_IMM64",
155 { "OPERAND_TYPE_BASEINDEX",
157 { "OPERAND_TYPE_DISP8",
159 { "OPERAND_TYPE_DISP16",
161 { "OPERAND_TYPE_DISP32",
163 { "OPERAND_TYPE_DISP32S",
165 { "OPERAND_TYPE_DISP64",
167 { "OPERAND_TYPE_INOUTPORTREG",
169 { "OPERAND_TYPE_SHIFTCOUNT",
171 { "OPERAND_TYPE_CONTROL",
173 { "OPERAND_TYPE_TEST",
175 { "OPERAND_TYPE_DEBUG",
177 { "OPERAND_TYPE_FLOATREG",
179 { "OPERAND_TYPE_FLOATACC",
181 { "OPERAND_TYPE_SREG2",
183 { "OPERAND_TYPE_SREG3",
185 { "OPERAND_TYPE_ACC",
187 { "OPERAND_TYPE_JUMPABSOLUTE",
189 { "OPERAND_TYPE_REGMMX",
191 { "OPERAND_TYPE_REGXMM",
193 { "OPERAND_TYPE_REGYMM",
195 { "OPERAND_TYPE_ESSEG",
197 { "OPERAND_TYPE_ACC32",
199 { "OPERAND_TYPE_ACC64",
201 { "OPERAND_TYPE_INOUTPORTREG",
203 { "OPERAND_TYPE_REG16_INOUTPORTREG",
204 "Reg16|InOutPortReg" },
205 { "OPERAND_TYPE_DISP16_32",
207 { "OPERAND_TYPE_ANYDISP",
208 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
209 { "OPERAND_TYPE_IMM16_32",
211 { "OPERAND_TYPE_IMM16_32S",
213 { "OPERAND_TYPE_IMM16_32_32S",
214 "Imm16|Imm32|Imm32S" },
215 { "OPERAND_TYPE_IMM32_32S_DISP32",
216 "Imm32|Imm32S|Disp32" },
217 { "OPERAND_TYPE_IMM64_DISP64",
219 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
220 "Imm32|Imm32S|Imm64|Disp32" },
221 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
222 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
223 { "OPERAND_TYPE_VEX_IMM4",
227 typedef struct bitfield
234 #define BITFIELD(n) { n, 0, #n }
236 static bitfield cpu_flags
[] =
252 BITFIELD (CpuSSE4_1
),
253 BITFIELD (CpuSSE4_2
),
258 BITFIELD (Cpu3dnowA
),
259 BITFIELD (CpuPadLock
),
266 BITFIELD (CpuPCLMUL
),
272 BITFIELD (CpuUnused
),
276 static bitfield opcode_modifiers
[] =
281 BITFIELD (ShortForm
),
283 BITFIELD (JumpDword
),
285 BITFIELD (JumpInterSegment
),
292 BITFIELD (IgnoreSize
),
293 BITFIELD (DefaultSize
),
302 BITFIELD (RegKludge
),
303 BITFIELD (FirstXmm0
),
304 BITFIELD (Implicit1stXmm0
),
305 BITFIELD (ByteOkIntel
),
308 BITFIELD (AddrPrefixOp0
),
326 BITFIELD (Vex3Sources
),
327 BITFIELD (VexImmExt
),
331 BITFIELD (ATTMnemonic
),
332 BITFIELD (ATTSyntax
),
333 BITFIELD (IntelSyntax
),
336 static bitfield operand_types
[] =
353 BITFIELD (BaseIndex
),
359 BITFIELD (InOutPortReg
),
360 BITFIELD (ShiftCount
),
368 BITFIELD (JumpAbsolute
),
380 BITFIELD (Unspecified
),
389 static const char *filename
;
392 compare (const void *x
, const void *y
)
394 const bitfield
*xp
= (const bitfield
*) x
;
395 const bitfield
*yp
= (const bitfield
*) y
;
396 return xp
->position
- yp
->position
;
400 fail (const char *message
, ...)
404 va_start (args
, message
);
405 fprintf (stderr
, _("%s: Error: "), program_name
);
406 vfprintf (stderr
, message
, args
);
412 process_copyright (FILE *fp
)
414 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
415 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
417 This file is part of the GNU opcodes library.\n\
419 This library is free software; you can redistribute it and/or modify\n\
420 it under the terms of the GNU General Public License as published by\n\
421 the Free Software Foundation; either version 3, or (at your option)\n\
422 any later version.\n\
424 It is distributed in the hope that it will be useful, but WITHOUT\n\
425 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
426 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
427 License for more details.\n\
429 You should have received a copy of the GNU General Public License\n\
430 along with this program; if not, write to the Free Software\n\
431 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
432 MA 02110-1301, USA. */\n");
435 /* Remove leading white spaces. */
438 remove_leading_whitespaces (char *str
)
440 while (ISSPACE (*str
))
445 /* Remove trailing white spaces. */
448 remove_trailing_whitespaces (char *str
)
450 size_t last
= strlen (str
);
458 if (ISSPACE (str
[last
]))
466 /* Find next field separated by SEP and terminate it. Return a
467 pointer to the one after it. */
470 next_field (char *str
, char sep
, char **next
)
474 p
= remove_leading_whitespaces (str
);
475 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
478 remove_trailing_whitespaces (p
);
486 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
490 if (strcmp (f
, "CpuSledgehammer") == 0)
492 else if (strcmp (f
, "Mmword") == 0)
494 else if (strcmp (f
, "Oword") == 0)
497 for (i
= 0; i
< size
; i
++)
498 if (strcasecmp (array
[i
].name
, f
) == 0)
504 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
508 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
509 int macro
, const char *comma
, const char *indent
)
513 fprintf (table
, "%s{ { ", indent
);
515 for (i
= 0; i
< size
- 1; i
++)
517 fprintf (table
, "%d, ", flags
[i
].value
);
518 if (((i
+ 1) % 20) == 0)
520 /* We need \\ for macro. */
522 fprintf (table
, " \\\n %s", indent
);
524 fprintf (table
, "\n %s", indent
);
528 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
532 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
533 const char *comma
, const char *indent
)
535 char *str
, *next
, *last
;
536 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
538 /* Copy the default cpu flags. */
539 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
541 if (strcasecmp (flag
, "unknown") == 0)
545 /* We turn on everything except for cpu64 in case of
546 CPU_UNKNOWN_FLAGS. */
547 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
548 if (flags
[i
].position
!= Cpu64
)
551 else if (strcmp (flag
, "0"))
553 last
= flag
+ strlen (flag
);
554 for (next
= flag
; next
&& next
< last
; )
556 str
= next_field (next
, '|', &next
);
558 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
562 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
567 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
571 fprintf (table
, " { ");
573 for (i
= 0; i
< size
- 1; i
++)
575 fprintf (table
, "%d, ", modifier
[i
].value
);
576 if (((i
+ 1) % 20) == 0)
577 fprintf (table
, "\n ");
580 fprintf (table
, "%d },\n", modifier
[i
].value
);
584 process_i386_opcode_modifier (FILE *table
, char *mod
)
586 char *str
, *next
, *last
;
587 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
589 /* Copy the default opcode modifier. */
590 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
592 if (strcmp (mod
, "0"))
594 last
= mod
+ strlen (mod
);
595 for (next
= mod
; next
&& next
< last
; )
597 str
= next_field (next
, '|', &next
);
599 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
602 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
606 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
607 int macro
, const char *indent
)
611 fprintf (table
, "{ { ");
613 for (i
= 0; i
< size
- 1; i
++)
615 fprintf (table
, "%d, ", types
[i
].value
);
616 if (((i
+ 1) % 20) == 0)
618 /* We need \\ for macro. */
620 fprintf (table
, "\\\n%s", indent
);
622 fprintf (table
, "\n%s", indent
);
626 fprintf (table
, "%d } }", types
[i
].value
);
630 process_i386_operand_type (FILE *table
, char *op
, int macro
,
633 char *str
, *next
, *last
;
634 bitfield types
[ARRAY_SIZE (operand_types
)];
636 /* Copy the default operand type. */
637 memcpy (types
, operand_types
, sizeof (types
));
639 if (strcmp (op
, "0"))
641 last
= op
+ strlen (op
);
642 for (next
= op
; next
&& next
< last
; )
644 str
= next_field (next
, '|', &next
);
646 set_bitfield (str
, types
, ARRAY_SIZE (types
));
649 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
654 process_i386_opcodes (FILE *table
)
659 char *str
, *p
, *last
;
660 char *name
, *operands
, *base_opcode
, *extension_opcode
;
662 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
664 filename
= "i386-opc.tbl";
665 fp
= fopen (filename
, "r");
668 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
671 fprintf (table
, "\n/* i386 opcode table. */\n\n");
672 fprintf (table
, "const template i386_optab[] =\n{\n");
676 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
681 p
= remove_leading_whitespaces (buf
);
684 str
= strstr (p
, "//");
688 /* Remove trailing white spaces. */
689 remove_trailing_whitespaces (p
);
694 fprintf (table
, "%s\n", p
);
702 last
= p
+ strlen (p
);
705 name
= next_field (p
, ',', &str
);
710 /* Find number of operands. */
711 operands
= next_field (str
, ',', &str
);
716 /* Find base_opcode. */
717 base_opcode
= next_field (str
, ',', &str
);
722 /* Find extension_opcode. */
723 extension_opcode
= next_field (str
, ',', &str
);
728 /* Find opcode_length. */
729 opcode_length
= next_field (str
, ',', &str
);
734 /* Find cpu_flags. */
735 cpu_flags
= next_field (str
, ',', &str
);
740 /* Find opcode_modifier. */
741 opcode_modifier
= next_field (str
, ',', &str
);
746 /* Remove the first {. */
747 str
= remove_leading_whitespaces (str
);
750 str
= remove_leading_whitespaces (str
+ 1);
754 /* There are at least "X}". */
758 /* Remove trailing white spaces and }. */
762 if (ISSPACE (str
[i
]) || str
[i
] == '}')
771 /* Find operand_types. */
772 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
776 operand_types
[i
] = NULL
;
780 operand_types
[i
] = next_field (str
, ',', &str
);
781 if (*operand_types
[i
] == '0')
784 operand_types
[i
] = NULL
;
789 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
790 name
, operands
, base_opcode
, extension_opcode
,
793 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
795 process_i386_opcode_modifier (table
, opcode_modifier
);
797 fprintf (table
, " { ");
799 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
801 if (operand_types
[i
] == NULL
802 || *operand_types
[i
] == '0')
805 process_i386_operand_type (table
, "0", 0, "\t ");
810 fprintf (table
, ",\n ");
812 process_i386_operand_type (table
, operand_types
[i
], 0,
815 fprintf (table
, " } },\n");
820 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
822 process_i386_cpu_flag (table
, "0", 0, ",", " ");
824 process_i386_opcode_modifier (table
, "0");
826 fprintf (table
, " { ");
827 process_i386_operand_type (table
, "0", 0, "\t ");
828 fprintf (table
, " } }\n");
830 fprintf (table
, "};\n");
834 process_i386_registers (FILE *table
)
838 char *str
, *p
, *last
;
839 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
840 char *dw2_32_num
, *dw2_64_num
;
842 filename
= "i386-reg.tbl";
843 fp
= fopen (filename
, "r");
845 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
848 fprintf (table
, "\n/* i386 register table. */\n\n");
849 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
853 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
858 p
= remove_leading_whitespaces (buf
);
861 str
= strstr (p
, "//");
865 /* Remove trailing white spaces. */
866 remove_trailing_whitespaces (p
);
871 fprintf (table
, "%s\n", p
);
879 last
= p
+ strlen (p
);
882 reg_name
= next_field (p
, ',', &str
);
888 reg_type
= next_field (str
, ',', &str
);
893 /* Find reg_flags. */
894 reg_flags
= next_field (str
, ',', &str
);
900 reg_num
= next_field (str
, ',', &str
);
905 fprintf (table
, " { \"%s\",\n ", reg_name
);
907 process_i386_operand_type (table
, reg_type
, 0, "\t");
909 /* Find 32-bit Dwarf2 register number. */
910 dw2_32_num
= next_field (str
, ',', &str
);
915 /* Find 64-bit Dwarf2 register number. */
916 dw2_64_num
= next_field (str
, ',', &str
);
918 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
919 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
924 fprintf (table
, "};\n");
926 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
930 process_i386_initializers (void)
933 FILE *fp
= fopen ("i386-init.h", "w");
937 fail (_("can't create i386-init.h, errno = %s\n"),
940 process_copyright (fp
);
942 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
944 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
945 init
= xstrdup (cpu_flag_init
[i
].init
);
946 process_i386_cpu_flag (fp
, init
, 1, "", " ");
950 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
952 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
953 init
= xstrdup (operand_type_init
[i
].init
);
954 process_i386_operand_type (fp
, init
, 1, " ");
962 /* Program options. */
963 #define OPTION_SRCDIR 200
965 struct option long_options
[] =
967 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
968 {"debug", no_argument
, NULL
, 'd'},
969 {"version", no_argument
, NULL
, 'V'},
970 {"help", no_argument
, NULL
, 'h'},
971 {0, no_argument
, NULL
, 0}
977 printf ("%s: version 1.0\n", program_name
);
982 usage (FILE * stream
, int status
)
984 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
990 main (int argc
, char **argv
)
992 extern int chdir (char *);
997 program_name
= *argv
;
998 xmalloc_set_program_name (program_name
);
1000 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1025 if (chdir (srcdir
) != 0)
1026 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1027 srcdir
, xstrerror (errno
));
1029 /* Check the unused bitfield in i386_cpu_flags. */
1031 c
= CpuNumOfBits
- CpuMax
- 1;
1033 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1036 /* Check the unused bitfield in i386_operand_type. */
1038 c
= OTNumOfBits
- OTMax
- 1;
1040 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1043 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1046 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1047 sizeof (opcode_modifiers
[0]), compare
);
1049 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1050 sizeof (operand_types
[0]), compare
);
1052 table
= fopen ("i386-tbl.h", "w");
1054 fail (_("can't create i386-tbl.h, errno = %s\n"),
1057 process_copyright (table
);
1059 process_i386_opcodes (table
);
1060 process_i386_registers (table
);
1061 process_i386_initializers ();