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|CpuSSE4_2_Or_ABM|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|CpuSSE4_2_Or_ABM" },
101 { "CPU_3DNOWA_FLAGS",
102 "CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA" },
103 { "CPU_PADLOCK_FLAGS",
108 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
110 "CpuABM|CpuSSE4_2_Or_ABM" },
112 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5|CpuSSE4_1_Or_5|CpuSSE4_2_Or_ABM"},
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
),
238 BITFIELD (CpuSSE4_2_Or_ABM
),
240 BITFIELD (Cpu3dnowA
),
241 BITFIELD (CpuPadLock
),
250 BITFIELD (CpuUnused
),
254 static bitfield opcode_modifiers
[] =
259 BITFIELD (ShortForm
),
261 BITFIELD (JumpDword
),
263 BITFIELD (JumpInterSegment
),
270 BITFIELD (IgnoreSize
),
271 BITFIELD (DefaultSize
),
279 BITFIELD (CheckSize
),
287 BITFIELD (RegKludge
),
288 BITFIELD (FirstXmm0
),
289 BITFIELD (ByteOkIntel
),
292 BITFIELD (AddrPrefixOp0
),
302 BITFIELD (ATTMnemonic
),
303 BITFIELD (IntelMnemonic
),
306 static bitfield operand_types
[] =
322 BITFIELD (BaseIndex
),
328 BITFIELD (InOutPortReg
),
329 BITFIELD (ShiftCount
),
337 BITFIELD (JumpAbsolute
),
346 compare (const void *x
, const void *y
)
348 const bitfield
*xp
= (const bitfield
*) x
;
349 const bitfield
*yp
= (const bitfield
*) y
;
350 return xp
->position
- yp
->position
;
354 fail (const char *message
, ...)
358 va_start (args
, message
);
359 fprintf (stderr
, _("%s: Error: "), program_name
);
360 vfprintf (stderr
, message
, args
);
366 process_copyright (FILE *fp
)
368 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
369 /* Copyright 2007 Free Software Foundation, Inc.\n\
371 This file is part of the GNU opcodes library.\n\
373 This library is free software; you can redistribute it and/or modify\n\
374 it under the terms of the GNU General Public License as published by\n\
375 the Free Software Foundation; either version 3, or (at your option)\n\
376 any later version.\n\
378 It is distributed in the hope that it will be useful, but WITHOUT\n\
379 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
380 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
381 License for more details.\n\
383 You should have received a copy of the GNU General Public License\n\
384 along with this program; if not, write to the Free Software\n\
385 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
386 MA 02110-1301, USA. */\n");
389 /* Remove leading white spaces. */
392 remove_leading_whitespaces (char *str
)
394 while (ISSPACE (*str
))
399 /* Remove trailing white spaces. */
402 remove_trailing_whitespaces (char *str
)
404 size_t last
= strlen (str
);
412 if (ISSPACE (str
[last
]))
420 /* Find next field separated by SEP and terminate it. Return a
421 pointer to the one after it. */
424 next_field (char *str
, char sep
, char **next
)
428 p
= remove_leading_whitespaces (str
);
429 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
432 remove_trailing_whitespaces (p
);
440 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
444 if (strcmp (f
, "CpuSledgehammer") == 0)
447 for (i
= 0; i
< size
; i
++)
448 if (strcasecmp (array
[i
].name
, f
) == 0)
454 printf ("Unknown bitfield: %s\n", f
);
459 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
460 int macro
, const char *comma
, const char *indent
)
464 fprintf (table
, "%s{ { ", indent
);
466 for (i
= 0; i
< size
- 1; i
++)
468 fprintf (table
, "%d, ", flags
[i
].value
);
469 if (((i
+ 1) % 20) == 0)
471 /* We need \\ for macro. */
473 fprintf (table
, " \\\n %s", indent
);
475 fprintf (table
, "\n %s", indent
);
479 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
483 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
484 const char *comma
, const char *indent
)
486 char *str
, *next
, *last
;
487 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
489 /* Copy the default cpu flags. */
490 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
492 if (strcasecmp (flag
, "unknown") == 0)
496 /* We turn on everything except for cpu64 in case of
497 CPU_UNKNOWN_FLAGS. */
498 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
499 if (flags
[i
].position
!= Cpu64
)
502 else if (strcmp (flag
, "0"))
504 last
= flag
+ strlen (flag
);
505 for (next
= flag
; next
&& next
< last
; )
507 str
= next_field (next
, '|', &next
);
509 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
513 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
518 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
522 fprintf (table
, " { ");
524 for (i
= 0; i
< size
- 1; i
++)
526 fprintf (table
, "%d, ", modifier
[i
].value
);
527 if (((i
+ 1) % 20) == 0)
528 fprintf (table
, "\n ");
531 fprintf (table
, "%d },\n", modifier
[i
].value
);
535 process_i386_opcode_modifier (FILE *table
, char *mod
)
537 char *str
, *next
, *last
;
538 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
540 /* Copy the default opcode modifier. */
541 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
543 if (strcmp (mod
, "0"))
545 last
= mod
+ strlen (mod
);
546 for (next
= mod
; next
&& next
< last
; )
548 str
= next_field (next
, '|', &next
);
550 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
553 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
557 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
558 int macro
, const char *indent
)
562 fprintf (table
, "{ { ");
564 for (i
= 0; i
< size
- 1; i
++)
566 fprintf (table
, "%d, ", types
[i
].value
);
567 if (((i
+ 1) % 20) == 0)
569 /* We need \\ for macro. */
571 fprintf (table
, "\\\n%s", indent
);
573 fprintf (table
, "\n%s", indent
);
577 fprintf (table
, "%d } }", types
[i
].value
);
581 process_i386_operand_type (FILE *table
, char *op
, int macro
,
584 char *str
, *next
, *last
;
585 bitfield types
[ARRAY_SIZE (operand_types
)];
587 /* Copy the default operand type. */
588 memcpy (types
, operand_types
, sizeof (types
));
590 if (strcmp (op
, "0"))
592 last
= op
+ strlen (op
);
593 for (next
= op
; next
&& next
< last
; )
595 str
= next_field (next
, '|', &next
);
597 set_bitfield (str
, types
, ARRAY_SIZE (types
));
600 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
605 process_i386_opcodes (FILE *table
)
607 FILE *fp
= fopen ("i386-opc.tbl", "r");
610 char *str
, *p
, *last
;
611 char *name
, *operands
, *base_opcode
, *extension_opcode
;
613 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
616 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
619 fprintf (table
, "\n/* i386 opcode table. */\n\n");
620 fprintf (table
, "const template i386_optab[] =\n{\n");
624 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
627 p
= remove_leading_whitespaces (buf
);
630 str
= strstr (p
, "//");
634 /* Remove trailing white spaces. */
635 remove_trailing_whitespaces (p
);
640 fprintf (table
, "%s\n", p
);
648 last
= p
+ strlen (p
);
651 name
= next_field (p
, ',', &str
);
656 /* Find number of operands. */
657 operands
= next_field (str
, ',', &str
);
662 /* Find base_opcode. */
663 base_opcode
= next_field (str
, ',', &str
);
668 /* Find extension_opcode. */
669 extension_opcode
= next_field (str
, ',', &str
);
674 /* Find opcode_length. */
675 opcode_length
= next_field (str
, ',', &str
);
680 /* Find cpu_flags. */
681 cpu_flags
= next_field (str
, ',', &str
);
686 /* Find opcode_modifier. */
687 opcode_modifier
= next_field (str
, ',', &str
);
692 /* Remove the first {. */
693 str
= remove_leading_whitespaces (str
);
696 str
= remove_leading_whitespaces (str
+ 1);
700 /* There are at least "X}". */
704 /* Remove trailing white spaces and }. */
708 if (ISSPACE (str
[i
]) || str
[i
] == '}')
717 /* Find operand_types. */
718 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
722 operand_types
[i
] = NULL
;
726 operand_types
[i
] = next_field (str
, ',', &str
);
727 if (*operand_types
[i
] == '0')
730 operand_types
[i
] = NULL
;
735 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
736 name
, operands
, base_opcode
, extension_opcode
,
739 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
741 process_i386_opcode_modifier (table
, opcode_modifier
);
743 fprintf (table
, " { ");
745 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
747 if (operand_types
[i
] == NULL
748 || *operand_types
[i
] == '0')
751 process_i386_operand_type (table
, "0", 0, "\t ");
756 fprintf (table
, ",\n ");
758 process_i386_operand_type (table
, operand_types
[i
], 0,
761 fprintf (table
, " } },\n");
766 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
768 process_i386_cpu_flag (table
, "0", 0, ",", " ");
770 process_i386_opcode_modifier (table
, "0");
772 fprintf (table
, " { ");
773 process_i386_operand_type (table
, "0", 0, "\t ");
774 fprintf (table
, " } }\n");
776 fprintf (table
, "};\n");
780 process_i386_registers (FILE *table
)
782 FILE *fp
= fopen ("i386-reg.tbl", "r");
784 char *str
, *p
, *last
;
785 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
788 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
791 fprintf (table
, "\n/* i386 register table. */\n\n");
792 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
796 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
799 p
= remove_leading_whitespaces (buf
);
802 str
= strstr (p
, "//");
806 /* Remove trailing white spaces. */
807 remove_trailing_whitespaces (p
);
812 fprintf (table
, "%s\n", p
);
820 last
= p
+ strlen (p
);
823 reg_name
= next_field (p
, ',', &str
);
829 reg_type
= next_field (str
, ',', &str
);
834 /* Find reg_flags. */
835 reg_flags
= next_field (str
, ',', &str
);
841 reg_num
= next_field (str
, ',', &str
);
843 fprintf (table
, " { \"%s\",\n ", reg_name
);
845 process_i386_operand_type (table
, reg_type
, 0, "\t");
847 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
852 fprintf (table
, "};\n");
854 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
858 process_i386_initializers (void)
861 FILE *fp
= fopen ("i386-init.h", "w");
865 fail (_("can't create i386-init.h, errno = %s\n"),
868 process_copyright (fp
);
870 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
872 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
873 init
= xstrdup (cpu_flag_init
[i
].init
);
874 process_i386_cpu_flag (fp
, init
, 1, "", " ");
878 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
880 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
881 init
= xstrdup (operand_type_init
[i
].init
);
882 process_i386_operand_type (fp
, init
, 1, " ");
890 /* Program options. */
891 #define OPTION_SRCDIR 200
893 struct option long_options
[] =
895 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
896 {"debug", no_argument
, NULL
, 'd'},
897 {"version", no_argument
, NULL
, 'V'},
898 {"help", no_argument
, NULL
, 'h'},
899 {0, no_argument
, NULL
, 0}
905 printf ("%s: version 1.0\n", program_name
);
910 usage (FILE * stream
, int status
)
912 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
918 main (int argc
, char **argv
)
920 extern int chdir (char *);
925 program_name
= *argv
;
926 xmalloc_set_program_name (program_name
);
928 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
953 if (chdir (srcdir
) != 0)
954 fail (_("unable to change directory to \"%s\", errno = %s\n"),
955 srcdir
, xstrerror (errno
));
957 /* Check the unused bitfield in i386_cpu_flags. */
959 c
= CpuNumOfBits
- CpuMax
- 1;
961 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
964 /* Check the unused bitfield in i386_operand_type. */
966 c
= OTNumOfBits
- OTMax
- 1;
968 fail (_("%d unused bits in i386_operand_type.\n"), c
);
971 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
974 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
975 sizeof (opcode_modifiers
[0]), compare
);
977 qsort (operand_types
, ARRAY_SIZE (operand_types
),
978 sizeof (operand_types
[0]), compare
);
980 table
= fopen ("i386-tbl.h", "w");
982 fail (_("can't create i386-tbl.h, errno = %s\n"),
985 process_copyright (table
);
987 process_i386_opcodes (table
);
988 process_i386_registers (table
);
989 process_i386_initializers ();