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|CpuSSE4_1_Or_5" },
98 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4_1_Or_5" },
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|CpuSSE4_1_Or_5"},
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
),
237 BITFIELD (CpuSSE4_1_Or_5
),
239 BITFIELD (Cpu3dnowA
),
240 BITFIELD (CpuPadLock
),
249 BITFIELD (CpuUnused
),
253 static bitfield opcode_modifiers
[] =
258 BITFIELD (ShortForm
),
260 BITFIELD (JumpDword
),
262 BITFIELD (JumpInterSegment
),
269 BITFIELD (IgnoreSize
),
270 BITFIELD (DefaultSize
),
278 BITFIELD (CheckSize
),
286 BITFIELD (RegKludge
),
287 BITFIELD (FirstXmm0
),
288 BITFIELD (ByteOkIntel
),
291 BITFIELD (AddrPrefixOp0
),
301 BITFIELD (ATTMnemonic
),
302 BITFIELD (IntelMnemonic
),
305 static bitfield operand_types
[] =
321 BITFIELD (BaseIndex
),
327 BITFIELD (InOutPortReg
),
328 BITFIELD (ShiftCount
),
336 BITFIELD (JumpAbsolute
),
345 compare (const void *x
, const void *y
)
347 const bitfield
*xp
= (const bitfield
*) x
;
348 const bitfield
*yp
= (const bitfield
*) y
;
349 return xp
->position
- yp
->position
;
353 fail (const char *message
, ...)
357 va_start (args
, message
);
358 fprintf (stderr
, _("%s: Error: "), program_name
);
359 vfprintf (stderr
, message
, args
);
365 process_copyright (FILE *fp
)
367 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
368 /* Copyright 2007 Free Software Foundation, Inc.\n\
370 This file is part of the GNU opcodes library.\n\
372 This library is free software; you can redistribute it and/or modify\n\
373 it under the terms of the GNU General Public License as published by\n\
374 the Free Software Foundation; either version 3, or (at your option)\n\
375 any later version.\n\
377 It is distributed in the hope that it will be useful, but WITHOUT\n\
378 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
379 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
380 License for more details.\n\
382 You should have received a copy of the GNU General Public License\n\
383 along with this program; if not, write to the Free Software\n\
384 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
385 MA 02110-1301, USA. */\n");
388 /* Remove leading white spaces. */
391 remove_leading_whitespaces (char *str
)
393 while (ISSPACE (*str
))
398 /* Remove trailing white spaces. */
401 remove_trailing_whitespaces (char *str
)
403 size_t last
= strlen (str
);
411 if (ISSPACE (str
[last
]))
419 /* Find next field separated by SEP and terminate it. Return a
420 pointer to the one after it. */
423 next_field (char *str
, char sep
, char **next
)
427 p
= remove_leading_whitespaces (str
);
428 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
431 remove_trailing_whitespaces (p
);
439 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
443 if (strcmp (f
, "CpuSledgehammer") == 0)
446 for (i
= 0; i
< size
; i
++)
447 if (strcasecmp (array
[i
].name
, f
) == 0)
453 printf ("Unknown bitfield: %s\n", 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
)
606 FILE *fp
= fopen ("i386-opc.tbl", "r");
609 char *str
, *p
, *last
;
610 char *name
, *operands
, *base_opcode
, *extension_opcode
;
612 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
615 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
618 fprintf (table
, "\n/* i386 opcode table. */\n\n");
619 fprintf (table
, "const template i386_optab[] =\n{\n");
623 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
626 p
= remove_leading_whitespaces (buf
);
629 str
= strstr (p
, "//");
633 /* Remove trailing white spaces. */
634 remove_trailing_whitespaces (p
);
639 fprintf (table
, "%s\n", p
);
647 last
= p
+ strlen (p
);
650 name
= next_field (p
, ',', &str
);
655 /* Find number of operands. */
656 operands
= next_field (str
, ',', &str
);
661 /* Find base_opcode. */
662 base_opcode
= next_field (str
, ',', &str
);
667 /* Find extension_opcode. */
668 extension_opcode
= next_field (str
, ',', &str
);
673 /* Find opcode_length. */
674 opcode_length
= next_field (str
, ',', &str
);
679 /* Find cpu_flags. */
680 cpu_flags
= next_field (str
, ',', &str
);
685 /* Find opcode_modifier. */
686 opcode_modifier
= next_field (str
, ',', &str
);
691 /* Remove the first {. */
692 str
= remove_leading_whitespaces (str
);
695 str
= remove_leading_whitespaces (str
+ 1);
699 /* There are at least "X}". */
703 /* Remove trailing white spaces and }. */
707 if (ISSPACE (str
[i
]) || str
[i
] == '}')
716 /* Find operand_types. */
717 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
721 operand_types
[i
] = NULL
;
725 operand_types
[i
] = next_field (str
, ',', &str
);
726 if (*operand_types
[i
] == '0')
729 operand_types
[i
] = NULL
;
734 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
735 name
, operands
, base_opcode
, extension_opcode
,
738 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
740 process_i386_opcode_modifier (table
, opcode_modifier
);
742 fprintf (table
, " { ");
744 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
746 if (operand_types
[i
] == NULL
747 || *operand_types
[i
] == '0')
750 process_i386_operand_type (table
, "0", 0, "\t ");
755 fprintf (table
, ",\n ");
757 process_i386_operand_type (table
, operand_types
[i
], 0,
760 fprintf (table
, " } },\n");
765 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
767 process_i386_cpu_flag (table
, "0", 0, ",", " ");
769 process_i386_opcode_modifier (table
, "0");
771 fprintf (table
, " { ");
772 process_i386_operand_type (table
, "0", 0, "\t ");
773 fprintf (table
, " } }\n");
775 fprintf (table
, "};\n");
779 process_i386_registers (FILE *table
)
781 FILE *fp
= fopen ("i386-reg.tbl", "r");
783 char *str
, *p
, *last
;
784 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
787 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
790 fprintf (table
, "\n/* i386 register table. */\n\n");
791 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
795 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
798 p
= remove_leading_whitespaces (buf
);
801 str
= strstr (p
, "//");
805 /* Remove trailing white spaces. */
806 remove_trailing_whitespaces (p
);
811 fprintf (table
, "%s\n", p
);
819 last
= p
+ strlen (p
);
822 reg_name
= next_field (p
, ',', &str
);
828 reg_type
= next_field (str
, ',', &str
);
833 /* Find reg_flags. */
834 reg_flags
= next_field (str
, ',', &str
);
840 reg_num
= next_field (str
, ',', &str
);
842 fprintf (table
, " { \"%s\",\n ", reg_name
);
844 process_i386_operand_type (table
, reg_type
, 0, "\t");
846 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
851 fprintf (table
, "};\n");
853 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
857 process_i386_initializers (void)
860 FILE *fp
= fopen ("i386-init.h", "w");
864 fail (_("can't create i386-init.h, errno = %s\n"),
867 process_copyright (fp
);
869 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
871 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
872 init
= xstrdup (cpu_flag_init
[i
].init
);
873 process_i386_cpu_flag (fp
, init
, 1, "", " ");
877 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
879 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
880 init
= xstrdup (operand_type_init
[i
].init
);
881 process_i386_operand_type (fp
, init
, 1, " ");
889 /* Program options. */
890 #define OPTION_SRCDIR 200
892 struct option long_options
[] =
894 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
895 {"debug", no_argument
, NULL
, 'd'},
896 {"version", no_argument
, NULL
, 'V'},
897 {"help", no_argument
, NULL
, 'h'},
898 {0, no_argument
, NULL
, 0}
904 printf ("%s: version 1.0\n", program_name
);
909 usage (FILE * stream
, int status
)
911 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
917 main (int argc
, char **argv
)
919 extern int chdir (char *);
924 program_name
= *argv
;
925 xmalloc_set_program_name (program_name
);
927 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
952 if (chdir (srcdir
) != 0)
953 fail (_("unable to change directory to \"%s\", errno = %s\n"),
954 srcdir
, xstrerror (errno
));
956 /* Check the unused bitfield in i386_cpu_flags. */
958 c
= CpuNumOfBits
- CpuMax
- 1;
960 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
963 /* Check the unused bitfield in i386_operand_type. */
965 c
= OTNumOfBits
- OTMax
- 1;
967 fail (_("%d unused bits in i386_operand_type.\n"), c
);
970 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
973 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
974 sizeof (opcode_modifiers
[0]), compare
);
976 qsort (operand_types
, ARRAY_SIZE (operand_types
),
977 sizeof (operand_types
[0]), compare
);
979 table
= fopen ("i386-tbl.h", "w");
981 fail (_("can't create i386-tbl.h, errno = %s\n"),
984 process_copyright (table
);
986 process_i386_opcodes (table
);
987 process_i386_registers (table
);
988 process_i386_initializers ();