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
),
330 BITFIELD (ATTMnemonic
),
331 BITFIELD (ATTSyntax
),
332 BITFIELD (IntelSyntax
),
335 static bitfield operand_types
[] =
352 BITFIELD (BaseIndex
),
358 BITFIELD (InOutPortReg
),
359 BITFIELD (ShiftCount
),
367 BITFIELD (JumpAbsolute
),
379 BITFIELD (Unspecified
),
388 static const char *filename
;
391 compare (const void *x
, const void *y
)
393 const bitfield
*xp
= (const bitfield
*) x
;
394 const bitfield
*yp
= (const bitfield
*) y
;
395 return xp
->position
- yp
->position
;
399 fail (const char *message
, ...)
403 va_start (args
, message
);
404 fprintf (stderr
, _("%s: Error: "), program_name
);
405 vfprintf (stderr
, message
, args
);
411 process_copyright (FILE *fp
)
413 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
414 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
416 This file is part of the GNU opcodes library.\n\
418 This library is free software; you can redistribute it and/or modify\n\
419 it under the terms of the GNU General Public License as published by\n\
420 the Free Software Foundation; either version 3, or (at your option)\n\
421 any later version.\n\
423 It is distributed in the hope that it will be useful, but WITHOUT\n\
424 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
425 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
426 License for more details.\n\
428 You should have received a copy of the GNU General Public License\n\
429 along with this program; if not, write to the Free Software\n\
430 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
431 MA 02110-1301, USA. */\n");
434 /* Remove leading white spaces. */
437 remove_leading_whitespaces (char *str
)
439 while (ISSPACE (*str
))
444 /* Remove trailing white spaces. */
447 remove_trailing_whitespaces (char *str
)
449 size_t last
= strlen (str
);
457 if (ISSPACE (str
[last
]))
465 /* Find next field separated by SEP and terminate it. Return a
466 pointer to the one after it. */
469 next_field (char *str
, char sep
, char **next
)
473 p
= remove_leading_whitespaces (str
);
474 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
477 remove_trailing_whitespaces (p
);
485 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
489 if (strcmp (f
, "CpuSledgehammer") == 0)
491 else if (strcmp (f
, "Mmword") == 0)
493 else if (strcmp (f
, "Oword") == 0)
496 for (i
= 0; i
< size
; i
++)
497 if (strcasecmp (array
[i
].name
, f
) == 0)
503 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
507 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
508 int macro
, const char *comma
, const char *indent
)
512 fprintf (table
, "%s{ { ", indent
);
514 for (i
= 0; i
< size
- 1; i
++)
516 fprintf (table
, "%d, ", flags
[i
].value
);
517 if (((i
+ 1) % 20) == 0)
519 /* We need \\ for macro. */
521 fprintf (table
, " \\\n %s", indent
);
523 fprintf (table
, "\n %s", indent
);
527 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
531 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
532 const char *comma
, const char *indent
)
534 char *str
, *next
, *last
;
535 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
537 /* Copy the default cpu flags. */
538 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
540 if (strcasecmp (flag
, "unknown") == 0)
544 /* We turn on everything except for cpu64 in case of
545 CPU_UNKNOWN_FLAGS. */
546 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
547 if (flags
[i
].position
!= Cpu64
)
550 else if (strcmp (flag
, "0"))
552 last
= flag
+ strlen (flag
);
553 for (next
= flag
; next
&& next
< last
; )
555 str
= next_field (next
, '|', &next
);
557 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
561 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
566 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
570 fprintf (table
, " { ");
572 for (i
= 0; i
< size
- 1; i
++)
574 fprintf (table
, "%d, ", modifier
[i
].value
);
575 if (((i
+ 1) % 20) == 0)
576 fprintf (table
, "\n ");
579 fprintf (table
, "%d },\n", modifier
[i
].value
);
583 process_i386_opcode_modifier (FILE *table
, char *mod
)
585 char *str
, *next
, *last
;
586 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
588 /* Copy the default opcode modifier. */
589 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
591 if (strcmp (mod
, "0"))
593 last
= mod
+ strlen (mod
);
594 for (next
= mod
; next
&& next
< last
; )
596 str
= next_field (next
, '|', &next
);
598 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
601 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
605 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
606 int macro
, const char *indent
)
610 fprintf (table
, "{ { ");
612 for (i
= 0; i
< size
- 1; i
++)
614 fprintf (table
, "%d, ", types
[i
].value
);
615 if (((i
+ 1) % 20) == 0)
617 /* We need \\ for macro. */
619 fprintf (table
, "\\\n%s", indent
);
621 fprintf (table
, "\n%s", indent
);
625 fprintf (table
, "%d } }", types
[i
].value
);
629 process_i386_operand_type (FILE *table
, char *op
, int macro
,
632 char *str
, *next
, *last
;
633 bitfield types
[ARRAY_SIZE (operand_types
)];
635 /* Copy the default operand type. */
636 memcpy (types
, operand_types
, sizeof (types
));
638 if (strcmp (op
, "0"))
640 last
= op
+ strlen (op
);
641 for (next
= op
; next
&& next
< last
; )
643 str
= next_field (next
, '|', &next
);
645 set_bitfield (str
, types
, ARRAY_SIZE (types
));
648 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
653 process_i386_opcodes (FILE *table
)
658 char *str
, *p
, *last
;
659 char *name
, *operands
, *base_opcode
, *extension_opcode
;
661 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
663 filename
= "i386-opc.tbl";
664 fp
= fopen (filename
, "r");
667 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
670 fprintf (table
, "\n/* i386 opcode table. */\n\n");
671 fprintf (table
, "const template i386_optab[] =\n{\n");
675 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
680 p
= remove_leading_whitespaces (buf
);
683 str
= strstr (p
, "//");
687 /* Remove trailing white spaces. */
688 remove_trailing_whitespaces (p
);
693 fprintf (table
, "%s\n", p
);
701 last
= p
+ strlen (p
);
704 name
= next_field (p
, ',', &str
);
709 /* Find number of operands. */
710 operands
= next_field (str
, ',', &str
);
715 /* Find base_opcode. */
716 base_opcode
= next_field (str
, ',', &str
);
721 /* Find extension_opcode. */
722 extension_opcode
= next_field (str
, ',', &str
);
727 /* Find opcode_length. */
728 opcode_length
= next_field (str
, ',', &str
);
733 /* Find cpu_flags. */
734 cpu_flags
= next_field (str
, ',', &str
);
739 /* Find opcode_modifier. */
740 opcode_modifier
= next_field (str
, ',', &str
);
745 /* Remove the first {. */
746 str
= remove_leading_whitespaces (str
);
749 str
= remove_leading_whitespaces (str
+ 1);
753 /* There are at least "X}". */
757 /* Remove trailing white spaces and }. */
761 if (ISSPACE (str
[i
]) || str
[i
] == '}')
770 /* Find operand_types. */
771 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
775 operand_types
[i
] = NULL
;
779 operand_types
[i
] = next_field (str
, ',', &str
);
780 if (*operand_types
[i
] == '0')
783 operand_types
[i
] = NULL
;
788 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
789 name
, operands
, base_opcode
, extension_opcode
,
792 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
794 process_i386_opcode_modifier (table
, opcode_modifier
);
796 fprintf (table
, " { ");
798 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
800 if (operand_types
[i
] == NULL
801 || *operand_types
[i
] == '0')
804 process_i386_operand_type (table
, "0", 0, "\t ");
809 fprintf (table
, ",\n ");
811 process_i386_operand_type (table
, operand_types
[i
], 0,
814 fprintf (table
, " } },\n");
819 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
821 process_i386_cpu_flag (table
, "0", 0, ",", " ");
823 process_i386_opcode_modifier (table
, "0");
825 fprintf (table
, " { ");
826 process_i386_operand_type (table
, "0", 0, "\t ");
827 fprintf (table
, " } }\n");
829 fprintf (table
, "};\n");
833 process_i386_registers (FILE *table
)
837 char *str
, *p
, *last
;
838 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
839 char *dw2_32_num
, *dw2_64_num
;
841 filename
= "i386-reg.tbl";
842 fp
= fopen (filename
, "r");
844 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
847 fprintf (table
, "\n/* i386 register table. */\n\n");
848 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
852 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
857 p
= remove_leading_whitespaces (buf
);
860 str
= strstr (p
, "//");
864 /* Remove trailing white spaces. */
865 remove_trailing_whitespaces (p
);
870 fprintf (table
, "%s\n", p
);
878 last
= p
+ strlen (p
);
881 reg_name
= next_field (p
, ',', &str
);
887 reg_type
= next_field (str
, ',', &str
);
892 /* Find reg_flags. */
893 reg_flags
= next_field (str
, ',', &str
);
899 reg_num
= next_field (str
, ',', &str
);
904 fprintf (table
, " { \"%s\",\n ", reg_name
);
906 process_i386_operand_type (table
, reg_type
, 0, "\t");
908 /* Find 32-bit Dwarf2 register number. */
909 dw2_32_num
= next_field (str
, ',', &str
);
914 /* Find 64-bit Dwarf2 register number. */
915 dw2_64_num
= next_field (str
, ',', &str
);
917 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
918 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
923 fprintf (table
, "};\n");
925 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
929 process_i386_initializers (void)
932 FILE *fp
= fopen ("i386-init.h", "w");
936 fail (_("can't create i386-init.h, errno = %s\n"),
939 process_copyright (fp
);
941 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
943 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
944 init
= xstrdup (cpu_flag_init
[i
].init
);
945 process_i386_cpu_flag (fp
, init
, 1, "", " ");
949 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
951 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
952 init
= xstrdup (operand_type_init
[i
].init
);
953 process_i386_operand_type (fp
, init
, 1, " ");
961 /* Program options. */
962 #define OPTION_SRCDIR 200
964 struct option long_options
[] =
966 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
967 {"debug", no_argument
, NULL
, 'd'},
968 {"version", no_argument
, NULL
, 'V'},
969 {"help", no_argument
, NULL
, 'h'},
970 {0, no_argument
, NULL
, 0}
976 printf ("%s: version 1.0\n", program_name
);
981 usage (FILE * stream
, int status
)
983 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
989 main (int argc
, char **argv
)
991 extern int chdir (char *);
996 program_name
= *argv
;
997 xmalloc_set_program_name (program_name
);
999 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1024 if (chdir (srcdir
) != 0)
1025 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1026 srcdir
, xstrerror (errno
));
1028 /* Check the unused bitfield in i386_cpu_flags. */
1030 c
= CpuNumOfBits
- CpuMax
- 1;
1032 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1035 /* Check the unused bitfield in i386_operand_type. */
1037 c
= OTNumOfBits
- OTMax
- 1;
1039 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1042 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1045 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1046 sizeof (opcode_modifiers
[0]), compare
);
1048 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1049 sizeof (operand_types
[0]), compare
);
1051 table
= fopen ("i386-tbl.h", "w");
1053 fail (_("can't create i386-tbl.h, errno = %s\n"),
1056 process_copyright (table
);
1058 process_i386_opcodes (table
);
1059 process_i386_registers (table
);
1060 process_i386_initializers ();