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
),
248 BITFIELD (CpuUnused
),
252 static bitfield opcode_modifiers
[] =
257 BITFIELD (ShortForm
),
259 BITFIELD (JumpDword
),
261 BITFIELD (JumpInterSegment
),
268 BITFIELD (IgnoreSize
),
269 BITFIELD (DefaultSize
),
278 BITFIELD (RegKludge
),
279 BITFIELD (FirstXmm0
),
280 BITFIELD (ByteOkIntel
),
283 BITFIELD (AddrPrefixOp0
),
293 BITFIELD (ATTMnemonic
),
294 BITFIELD (IntelMnemonic
),
297 static bitfield operand_types
[] =
313 BITFIELD (BaseIndex
),
319 BITFIELD (InOutPortReg
),
320 BITFIELD (ShiftCount
),
328 BITFIELD (JumpAbsolute
),
337 compare (const void *x
, const void *y
)
339 const bitfield
*xp
= (const bitfield
*) x
;
340 const bitfield
*yp
= (const bitfield
*) y
;
341 return xp
->position
- yp
->position
;
345 fail (const char *message
, ...)
349 va_start (args
, message
);
350 fprintf (stderr
, _("%s: Error: "), program_name
);
351 vfprintf (stderr
, message
, args
);
357 process_copyright (FILE *fp
)
359 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
360 /* Copyright 2007 Free Software Foundation, Inc.\n\
362 This file is part of the GNU opcodes library.\n\
364 This library is free software; you can redistribute it and/or modify\n\
365 it under the terms of the GNU General Public License as published by\n\
366 the Free Software Foundation; either version 3, or (at your option)\n\
367 any later version.\n\
369 It is distributed in the hope that it will be useful, but WITHOUT\n\
370 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
371 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
372 License for more details.\n\
374 You should have received a copy of the GNU General Public License\n\
375 along with this program; if not, write to the Free Software\n\
376 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
377 MA 02110-1301, USA. */\n");
380 /* Remove leading white spaces. */
383 remove_leading_whitespaces (char *str
)
385 while (ISSPACE (*str
))
390 /* Remove trailing white spaces. */
393 remove_trailing_whitespaces (char *str
)
395 size_t last
= strlen (str
);
403 if (ISSPACE (str
[last
]))
411 /* Find next field separated by SEP and terminate it. Return a
412 pointer to the one after it. */
415 next_field (char *str
, char sep
, char **next
)
419 p
= remove_leading_whitespaces (str
);
420 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
423 remove_trailing_whitespaces (p
);
431 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
435 if (strcmp (f
, "CpuSledgehammer") == 0)
438 for (i
= 0; i
< size
; i
++)
439 if (strcasecmp (array
[i
].name
, f
) == 0)
445 printf ("Unknown bitfield: %s\n", f
);
450 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
451 int macro
, const char *comma
, const char *indent
)
455 fprintf (table
, "%s{ { ", indent
);
457 for (i
= 0; i
< size
- 1; i
++)
459 fprintf (table
, "%d, ", flags
[i
].value
);
460 if (((i
+ 1) % 20) == 0)
462 /* We need \\ for macro. */
464 fprintf (table
, " \\\n %s", indent
);
466 fprintf (table
, "\n %s", indent
);
470 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
474 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
475 const char *comma
, const char *indent
)
477 char *str
, *next
, *last
;
478 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
480 /* Copy the default cpu flags. */
481 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
483 if (strcasecmp (flag
, "unknown") == 0)
487 /* We turn on everything except for cpu64 in case of
488 CPU_UNKNOWN_FLAGS. */
489 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
490 if (flags
[i
].position
!= Cpu64
)
493 else if (strcmp (flag
, "0"))
495 last
= flag
+ strlen (flag
);
496 for (next
= flag
; next
&& next
< last
; )
498 str
= next_field (next
, '|', &next
);
500 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
504 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
509 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
513 fprintf (table
, " { ");
515 for (i
= 0; i
< size
- 1; i
++)
517 fprintf (table
, "%d, ", modifier
[i
].value
);
518 if (((i
+ 1) % 20) == 0)
519 fprintf (table
, "\n ");
522 fprintf (table
, "%d },\n", modifier
[i
].value
);
526 process_i386_opcode_modifier (FILE *table
, char *mod
)
528 char *str
, *next
, *last
;
529 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
531 /* Copy the default opcode modifier. */
532 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
534 if (strcmp (mod
, "0"))
536 last
= mod
+ strlen (mod
);
537 for (next
= mod
; next
&& next
< last
; )
539 str
= next_field (next
, '|', &next
);
541 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
544 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
548 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
549 int macro
, const char *indent
)
553 fprintf (table
, "{ { ");
555 for (i
= 0; i
< size
- 1; i
++)
557 fprintf (table
, "%d, ", types
[i
].value
);
558 if (((i
+ 1) % 20) == 0)
560 /* We need \\ for macro. */
562 fprintf (table
, "\\\n%s", indent
);
564 fprintf (table
, "\n%s", indent
);
568 fprintf (table
, "%d } }", types
[i
].value
);
572 process_i386_operand_type (FILE *table
, char *op
, int macro
,
575 char *str
, *next
, *last
;
576 bitfield types
[ARRAY_SIZE (operand_types
)];
578 /* Copy the default operand type. */
579 memcpy (types
, operand_types
, sizeof (types
));
581 if (strcmp (op
, "0"))
583 last
= op
+ strlen (op
);
584 for (next
= op
; next
&& next
< last
; )
586 str
= next_field (next
, '|', &next
);
588 set_bitfield (str
, types
, ARRAY_SIZE (types
));
591 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
596 process_i386_opcodes (FILE *table
)
598 FILE *fp
= fopen ("i386-opc.tbl", "r");
601 char *str
, *p
, *last
;
602 char *name
, *operands
, *base_opcode
, *extension_opcode
;
604 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
607 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
610 fprintf (table
, "\n/* i386 opcode table. */\n\n");
611 fprintf (table
, "const template i386_optab[] =\n{\n");
615 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
618 p
= remove_leading_whitespaces (buf
);
621 str
= strstr (p
, "//");
625 /* Remove trailing white spaces. */
626 remove_trailing_whitespaces (p
);
631 fprintf (table
, "%s\n", p
);
639 last
= p
+ strlen (p
);
642 name
= next_field (p
, ',', &str
);
647 /* Find number of operands. */
648 operands
= next_field (str
, ',', &str
);
653 /* Find base_opcode. */
654 base_opcode
= next_field (str
, ',', &str
);
659 /* Find extension_opcode. */
660 extension_opcode
= next_field (str
, ',', &str
);
665 /* Find opcode_length. */
666 opcode_length
= next_field (str
, ',', &str
);
671 /* Find cpu_flags. */
672 cpu_flags
= next_field (str
, ',', &str
);
677 /* Find opcode_modifier. */
678 opcode_modifier
= next_field (str
, ',', &str
);
683 /* Remove the first {. */
684 str
= remove_leading_whitespaces (str
);
687 str
= remove_leading_whitespaces (str
+ 1);
691 /* There are at least "X}". */
695 /* Remove trailing white spaces and }. */
699 if (ISSPACE (str
[i
]) || str
[i
] == '}')
708 /* Find operand_types. */
709 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
713 operand_types
[i
] = NULL
;
717 operand_types
[i
] = next_field (str
, ',', &str
);
718 if (*operand_types
[i
] == '0')
721 operand_types
[i
] = NULL
;
726 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
727 name
, operands
, base_opcode
, extension_opcode
,
730 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
732 process_i386_opcode_modifier (table
, opcode_modifier
);
734 fprintf (table
, " { ");
736 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
738 if (operand_types
[i
] == NULL
739 || *operand_types
[i
] == '0')
742 process_i386_operand_type (table
, "0", 0, "\t ");
747 fprintf (table
, ",\n ");
749 process_i386_operand_type (table
, operand_types
[i
], 0,
752 fprintf (table
, " } },\n");
757 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
759 process_i386_cpu_flag (table
, "0", 0, ",", " ");
761 process_i386_opcode_modifier (table
, "0");
763 fprintf (table
, " { ");
764 process_i386_operand_type (table
, "0", 0, "\t ");
765 fprintf (table
, " } }\n");
767 fprintf (table
, "};\n");
771 process_i386_registers (FILE *table
)
773 FILE *fp
= fopen ("i386-reg.tbl", "r");
775 char *str
, *p
, *last
;
776 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
779 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
782 fprintf (table
, "\n/* i386 register table. */\n\n");
783 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
787 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
790 p
= remove_leading_whitespaces (buf
);
793 str
= strstr (p
, "//");
797 /* Remove trailing white spaces. */
798 remove_trailing_whitespaces (p
);
803 fprintf (table
, "%s\n", p
);
811 last
= p
+ strlen (p
);
814 reg_name
= next_field (p
, ',', &str
);
820 reg_type
= next_field (str
, ',', &str
);
825 /* Find reg_flags. */
826 reg_flags
= next_field (str
, ',', &str
);
832 reg_num
= next_field (str
, ',', &str
);
834 fprintf (table
, " { \"%s\",\n ", reg_name
);
836 process_i386_operand_type (table
, reg_type
, 0, "\t");
838 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
843 fprintf (table
, "};\n");
845 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
849 process_i386_initializers (void)
852 FILE *fp
= fopen ("i386-init.h", "w");
856 fail (_("can't create i386-init.h, errno = %s\n"),
859 process_copyright (fp
);
861 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
863 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
864 init
= xstrdup (cpu_flag_init
[i
].init
);
865 process_i386_cpu_flag (fp
, init
, 1, "", " ");
869 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
871 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
872 init
= xstrdup (operand_type_init
[i
].init
);
873 process_i386_operand_type (fp
, init
, 1, " ");
881 /* Program options. */
882 #define OPTION_SRCDIR 200
884 struct option long_options
[] =
886 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
887 {"debug", no_argument
, NULL
, 'd'},
888 {"version", no_argument
, NULL
, 'V'},
889 {"help", no_argument
, NULL
, 'h'},
890 {0, no_argument
, NULL
, 0}
896 printf ("%s: version 1.0\n", program_name
);
901 usage (FILE * stream
, int status
)
903 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
909 main (int argc
, char **argv
)
911 extern int chdir (char *);
916 program_name
= *argv
;
917 xmalloc_set_program_name (program_name
);
919 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
944 if (chdir (srcdir
) != 0)
945 fail (_("unable to change directory to \"%s\", errno = %s\n"),
946 srcdir
, xstrerror (errno
));
948 /* Check the unused bitfield in i386_cpu_flags. */
950 c
= CpuNumOfBits
- CpuMax
- 1;
952 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
955 /* Check the unused bitfield in i386_operand_type. */
957 c
= OTNumOfBits
- OTMax
- 1;
959 fail (_("%d unused bits in i386_operand_type.\n"), c
);
962 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
965 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
966 sizeof (opcode_modifiers
[0]), compare
);
968 qsort (operand_types
, ARRAY_SIZE (operand_types
),
969 sizeof (operand_types
[0]), compare
);
971 table
= fopen ("i386-tbl.h", "w");
973 fail (_("can't create i386-tbl.h, errno = %s\n"),
976 process_copyright (table
);
978 process_i386_opcodes (table
);
979 process_i386_registers (table
);
980 process_i386_initializers ();