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
),
276 BITFIELD (CheckSize
),
284 BITFIELD (RegKludge
),
285 BITFIELD (FirstXmm0
),
286 BITFIELD (ByteOkIntel
),
289 BITFIELD (AddrPrefixOp0
),
299 BITFIELD (ATTMnemonic
),
300 BITFIELD (IntelMnemonic
),
303 static bitfield operand_types
[] =
319 BITFIELD (BaseIndex
),
325 BITFIELD (InOutPortReg
),
326 BITFIELD (ShiftCount
),
334 BITFIELD (JumpAbsolute
),
343 compare (const void *x
, const void *y
)
345 const bitfield
*xp
= (const bitfield
*) x
;
346 const bitfield
*yp
= (const bitfield
*) y
;
347 return xp
->position
- yp
->position
;
351 fail (const char *message
, ...)
355 va_start (args
, message
);
356 fprintf (stderr
, _("%s: Error: "), program_name
);
357 vfprintf (stderr
, message
, args
);
363 process_copyright (FILE *fp
)
365 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
366 /* Copyright 2007 Free Software Foundation, Inc.\n\
368 This file is part of the GNU opcodes library.\n\
370 This library is free software; you can redistribute it and/or modify\n\
371 it under the terms of the GNU General Public License as published by\n\
372 the Free Software Foundation; either version 3, or (at your option)\n\
373 any later version.\n\
375 It is distributed in the hope that it will be useful, but WITHOUT\n\
376 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
377 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
378 License for more details.\n\
380 You should have received a copy of the GNU General Public License\n\
381 along with this program; if not, write to the Free Software\n\
382 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
383 MA 02110-1301, USA. */\n");
386 /* Remove leading white spaces. */
389 remove_leading_whitespaces (char *str
)
391 while (ISSPACE (*str
))
396 /* Remove trailing white spaces. */
399 remove_trailing_whitespaces (char *str
)
401 size_t last
= strlen (str
);
409 if (ISSPACE (str
[last
]))
417 /* Find next field separated by SEP and terminate it. Return a
418 pointer to the one after it. */
421 next_field (char *str
, char sep
, char **next
)
425 p
= remove_leading_whitespaces (str
);
426 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
429 remove_trailing_whitespaces (p
);
437 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
441 if (strcmp (f
, "CpuSledgehammer") == 0)
444 for (i
= 0; i
< size
; i
++)
445 if (strcasecmp (array
[i
].name
, f
) == 0)
451 printf ("Unknown bitfield: %s\n", f
);
456 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
457 int macro
, const char *comma
, const char *indent
)
461 fprintf (table
, "%s{ { ", indent
);
463 for (i
= 0; i
< size
- 1; i
++)
465 fprintf (table
, "%d, ", flags
[i
].value
);
466 if (((i
+ 1) % 20) == 0)
468 /* We need \\ for macro. */
470 fprintf (table
, " \\\n %s", indent
);
472 fprintf (table
, "\n %s", indent
);
476 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
480 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
481 const char *comma
, const char *indent
)
483 char *str
, *next
, *last
;
484 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
486 /* Copy the default cpu flags. */
487 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
489 if (strcasecmp (flag
, "unknown") == 0)
493 /* We turn on everything except for cpu64 in case of
494 CPU_UNKNOWN_FLAGS. */
495 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
496 if (flags
[i
].position
!= Cpu64
)
499 else if (strcmp (flag
, "0"))
501 last
= flag
+ strlen (flag
);
502 for (next
= flag
; next
&& next
< last
; )
504 str
= next_field (next
, '|', &next
);
506 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
510 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
515 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
519 fprintf (table
, " { ");
521 for (i
= 0; i
< size
- 1; i
++)
523 fprintf (table
, "%d, ", modifier
[i
].value
);
524 if (((i
+ 1) % 20) == 0)
525 fprintf (table
, "\n ");
528 fprintf (table
, "%d },\n", modifier
[i
].value
);
532 process_i386_opcode_modifier (FILE *table
, char *mod
)
534 char *str
, *next
, *last
;
535 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
537 /* Copy the default opcode modifier. */
538 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
540 if (strcmp (mod
, "0"))
542 last
= mod
+ strlen (mod
);
543 for (next
= mod
; next
&& next
< last
; )
545 str
= next_field (next
, '|', &next
);
547 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
550 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
554 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
555 int macro
, const char *indent
)
559 fprintf (table
, "{ { ");
561 for (i
= 0; i
< size
- 1; i
++)
563 fprintf (table
, "%d, ", types
[i
].value
);
564 if (((i
+ 1) % 20) == 0)
566 /* We need \\ for macro. */
568 fprintf (table
, "\\\n%s", indent
);
570 fprintf (table
, "\n%s", indent
);
574 fprintf (table
, "%d } }", types
[i
].value
);
578 process_i386_operand_type (FILE *table
, char *op
, int macro
,
581 char *str
, *next
, *last
;
582 bitfield types
[ARRAY_SIZE (operand_types
)];
584 /* Copy the default operand type. */
585 memcpy (types
, operand_types
, sizeof (types
));
587 if (strcmp (op
, "0"))
589 last
= op
+ strlen (op
);
590 for (next
= op
; next
&& next
< last
; )
592 str
= next_field (next
, '|', &next
);
594 set_bitfield (str
, types
, ARRAY_SIZE (types
));
597 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
602 process_i386_opcodes (FILE *table
)
604 FILE *fp
= fopen ("i386-opc.tbl", "r");
607 char *str
, *p
, *last
;
608 char *name
, *operands
, *base_opcode
, *extension_opcode
;
610 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
613 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
616 fprintf (table
, "\n/* i386 opcode table. */\n\n");
617 fprintf (table
, "const template i386_optab[] =\n{\n");
621 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
624 p
= remove_leading_whitespaces (buf
);
627 str
= strstr (p
, "//");
631 /* Remove trailing white spaces. */
632 remove_trailing_whitespaces (p
);
637 fprintf (table
, "%s\n", p
);
645 last
= p
+ strlen (p
);
648 name
= next_field (p
, ',', &str
);
653 /* Find number of operands. */
654 operands
= next_field (str
, ',', &str
);
659 /* Find base_opcode. */
660 base_opcode
= next_field (str
, ',', &str
);
665 /* Find extension_opcode. */
666 extension_opcode
= next_field (str
, ',', &str
);
671 /* Find opcode_length. */
672 opcode_length
= next_field (str
, ',', &str
);
677 /* Find cpu_flags. */
678 cpu_flags
= next_field (str
, ',', &str
);
683 /* Find opcode_modifier. */
684 opcode_modifier
= next_field (str
, ',', &str
);
689 /* Remove the first {. */
690 str
= remove_leading_whitespaces (str
);
693 str
= remove_leading_whitespaces (str
+ 1);
697 /* There are at least "X}". */
701 /* Remove trailing white spaces and }. */
705 if (ISSPACE (str
[i
]) || str
[i
] == '}')
714 /* Find operand_types. */
715 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
719 operand_types
[i
] = NULL
;
723 operand_types
[i
] = next_field (str
, ',', &str
);
724 if (*operand_types
[i
] == '0')
727 operand_types
[i
] = NULL
;
732 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
733 name
, operands
, base_opcode
, extension_opcode
,
736 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
738 process_i386_opcode_modifier (table
, opcode_modifier
);
740 fprintf (table
, " { ");
742 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
744 if (operand_types
[i
] == NULL
745 || *operand_types
[i
] == '0')
748 process_i386_operand_type (table
, "0", 0, "\t ");
753 fprintf (table
, ",\n ");
755 process_i386_operand_type (table
, operand_types
[i
], 0,
758 fprintf (table
, " } },\n");
763 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
765 process_i386_cpu_flag (table
, "0", 0, ",", " ");
767 process_i386_opcode_modifier (table
, "0");
769 fprintf (table
, " { ");
770 process_i386_operand_type (table
, "0", 0, "\t ");
771 fprintf (table
, " } }\n");
773 fprintf (table
, "};\n");
777 process_i386_registers (FILE *table
)
779 FILE *fp
= fopen ("i386-reg.tbl", "r");
781 char *str
, *p
, *last
;
782 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
785 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
788 fprintf (table
, "\n/* i386 register table. */\n\n");
789 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
793 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
796 p
= remove_leading_whitespaces (buf
);
799 str
= strstr (p
, "//");
803 /* Remove trailing white spaces. */
804 remove_trailing_whitespaces (p
);
809 fprintf (table
, "%s\n", p
);
817 last
= p
+ strlen (p
);
820 reg_name
= next_field (p
, ',', &str
);
826 reg_type
= next_field (str
, ',', &str
);
831 /* Find reg_flags. */
832 reg_flags
= next_field (str
, ',', &str
);
838 reg_num
= next_field (str
, ',', &str
);
840 fprintf (table
, " { \"%s\",\n ", reg_name
);
842 process_i386_operand_type (table
, reg_type
, 0, "\t");
844 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
849 fprintf (table
, "};\n");
851 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
855 process_i386_initializers (void)
858 FILE *fp
= fopen ("i386-init.h", "w");
862 fail (_("can't create i386-init.h, errno = %s\n"),
865 process_copyright (fp
);
867 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
869 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
870 init
= xstrdup (cpu_flag_init
[i
].init
);
871 process_i386_cpu_flag (fp
, init
, 1, "", " ");
875 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
877 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
878 init
= xstrdup (operand_type_init
[i
].init
);
879 process_i386_operand_type (fp
, init
, 1, " ");
887 /* Program options. */
888 #define OPTION_SRCDIR 200
890 struct option long_options
[] =
892 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
893 {"debug", no_argument
, NULL
, 'd'},
894 {"version", no_argument
, NULL
, 'V'},
895 {"help", no_argument
, NULL
, 'h'},
896 {0, no_argument
, NULL
, 0}
902 printf ("%s: version 1.0\n", program_name
);
907 usage (FILE * stream
, int status
)
909 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
915 main (int argc
, char **argv
)
917 extern int chdir (char *);
922 program_name
= *argv
;
923 xmalloc_set_program_name (program_name
);
925 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
950 if (chdir (srcdir
) != 0)
951 fail (_("unable to change directory to \"%s\", errno = %s\n"),
952 srcdir
, xstrerror (errno
));
954 /* Check the unused bitfield in i386_cpu_flags. */
956 c
= CpuNumOfBits
- CpuMax
- 1;
958 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
961 /* Check the unused bitfield in i386_operand_type. */
963 c
= OTNumOfBits
- OTMax
- 1;
965 fail (_("%d unused bits in i386_operand_type.\n"), c
);
968 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
971 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
972 sizeof (opcode_modifiers
[0]), compare
);
974 qsort (operand_types
, ARRAY_SIZE (operand_types
),
975 sizeof (operand_types
[0]), compare
);
977 table
= fopen ("i386-tbl.h", "w");
979 fail (_("can't create i386-tbl.h, errno = %s\n"),
982 process_copyright (table
);
984 process_i386_opcodes (table
);
985 process_i386_registers (table
);
986 process_i386_initializers ();