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" },
105 { "CPU_3DNOWA_FLAGS",
106 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
107 { "CPU_PADLOCK_FLAGS",
112 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
116 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
119 static initializer operand_type_init
[] =
121 { "OPERAND_TYPE_NONE",
123 { "OPERAND_TYPE_REG8",
125 { "OPERAND_TYPE_REG16",
127 { "OPERAND_TYPE_REG32",
129 { "OPERAND_TYPE_REG64",
131 { "OPERAND_TYPE_IMM1",
133 { "OPERAND_TYPE_IMM8",
135 { "OPERAND_TYPE_IMM8S",
137 { "OPERAND_TYPE_IMM16",
139 { "OPERAND_TYPE_IMM32",
141 { "OPERAND_TYPE_IMM32S",
143 { "OPERAND_TYPE_IMM64",
145 { "OPERAND_TYPE_BASEINDEX",
147 { "OPERAND_TYPE_DISP8",
149 { "OPERAND_TYPE_DISP16",
151 { "OPERAND_TYPE_DISP32",
153 { "OPERAND_TYPE_DISP32S",
155 { "OPERAND_TYPE_DISP64",
157 { "OPERAND_TYPE_INOUTPORTREG",
159 { "OPERAND_TYPE_SHIFTCOUNT",
161 { "OPERAND_TYPE_CONTROL",
163 { "OPERAND_TYPE_TEST",
165 { "OPERAND_TYPE_DEBUG",
167 { "OPERAND_TYPE_FLOATREG",
169 { "OPERAND_TYPE_FLOATACC",
171 { "OPERAND_TYPE_SREG2",
173 { "OPERAND_TYPE_SREG3",
175 { "OPERAND_TYPE_ACC",
177 { "OPERAND_TYPE_JUMPABSOLUTE",
179 { "OPERAND_TYPE_REGMMX",
181 { "OPERAND_TYPE_REGXMM",
183 { "OPERAND_TYPE_ESSEG",
185 { "OPERAND_TYPE_ACC32",
187 { "OPERAND_TYPE_ACC64",
189 { "OPERAND_TYPE_REG16_INOUTPORTREG",
190 "Reg16|InOutPortReg" },
191 { "OPERAND_TYPE_DISP16_32",
193 { "OPERAND_TYPE_ANYDISP",
194 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
195 { "OPERAND_TYPE_IMM16_32",
197 { "OPERAND_TYPE_IMM16_32S",
199 { "OPERAND_TYPE_IMM16_32_32S",
200 "Imm16|Imm32|Imm32S" },
201 { "OPERAND_TYPE_IMM32_32S_DISP32",
202 "Imm32|Imm32S|Disp32" },
203 { "OPERAND_TYPE_IMM64_DISP64",
205 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
206 "Imm32|Imm32S|Imm64|Disp32" },
207 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
208 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
211 typedef struct bitfield
218 #define BITFIELD(n) { n, 0, #n }
220 static bitfield cpu_flags
[] =
236 BITFIELD (CpuSSE4_1
),
237 BITFIELD (CpuSSE4_2
),
241 BITFIELD (Cpu3dnowA
),
242 BITFIELD (CpuPadLock
),
251 BITFIELD (CpuUnused
),
255 static bitfield opcode_modifiers
[] =
260 BITFIELD (ShortForm
),
262 BITFIELD (JumpDword
),
264 BITFIELD (JumpInterSegment
),
271 BITFIELD (IgnoreSize
),
272 BITFIELD (DefaultSize
),
281 BITFIELD (RegKludge
),
282 BITFIELD (FirstXmm0
),
283 BITFIELD (ByteOkIntel
),
286 BITFIELD (AddrPrefixOp0
),
296 BITFIELD (ATTMnemonic
),
297 BITFIELD (ATTSyntax
),
298 BITFIELD (IntelSyntax
),
301 static bitfield operand_types
[] =
317 BITFIELD (BaseIndex
),
323 BITFIELD (InOutPortReg
),
324 BITFIELD (ShiftCount
),
332 BITFIELD (JumpAbsolute
),
343 BITFIELD (Unspecified
),
351 static const char *filename
;
354 compare (const void *x
, const void *y
)
356 const bitfield
*xp
= (const bitfield
*) x
;
357 const bitfield
*yp
= (const bitfield
*) y
;
358 return xp
->position
- yp
->position
;
362 fail (const char *message
, ...)
366 va_start (args
, message
);
367 fprintf (stderr
, _("%s: Error: "), program_name
);
368 vfprintf (stderr
, message
, args
);
374 process_copyright (FILE *fp
)
376 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
377 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
379 This file is part of the GNU opcodes library.\n\
381 This library is free software; you can redistribute it and/or modify\n\
382 it under the terms of the GNU General Public License as published by\n\
383 the Free Software Foundation; either version 3, or (at your option)\n\
384 any later version.\n\
386 It is distributed in the hope that it will be useful, but WITHOUT\n\
387 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
388 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
389 License for more details.\n\
391 You should have received a copy of the GNU General Public License\n\
392 along with this program; if not, write to the Free Software\n\
393 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
394 MA 02110-1301, USA. */\n");
397 /* Remove leading white spaces. */
400 remove_leading_whitespaces (char *str
)
402 while (ISSPACE (*str
))
407 /* Remove trailing white spaces. */
410 remove_trailing_whitespaces (char *str
)
412 size_t last
= strlen (str
);
420 if (ISSPACE (str
[last
]))
428 /* Find next field separated by SEP and terminate it. Return a
429 pointer to the one after it. */
432 next_field (char *str
, char sep
, char **next
)
436 p
= remove_leading_whitespaces (str
);
437 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
440 remove_trailing_whitespaces (p
);
448 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
452 if (strcmp (f
, "CpuSledgehammer") == 0)
454 else if (strcmp (f
, "Mmword") == 0)
456 else if (strcmp (f
, "Oword") == 0)
459 for (i
= 0; i
< size
; i
++)
460 if (strcasecmp (array
[i
].name
, f
) == 0)
466 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
470 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
471 int macro
, const char *comma
, const char *indent
)
475 fprintf (table
, "%s{ { ", indent
);
477 for (i
= 0; i
< size
- 1; i
++)
479 fprintf (table
, "%d, ", flags
[i
].value
);
480 if (((i
+ 1) % 20) == 0)
482 /* We need \\ for macro. */
484 fprintf (table
, " \\\n %s", indent
);
486 fprintf (table
, "\n %s", indent
);
490 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
494 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
495 const char *comma
, const char *indent
)
497 char *str
, *next
, *last
;
498 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
500 /* Copy the default cpu flags. */
501 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
503 if (strcasecmp (flag
, "unknown") == 0)
507 /* We turn on everything except for cpu64 in case of
508 CPU_UNKNOWN_FLAGS. */
509 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
510 if (flags
[i
].position
!= Cpu64
)
513 else if (strcmp (flag
, "0"))
515 last
= flag
+ strlen (flag
);
516 for (next
= flag
; next
&& next
< last
; )
518 str
= next_field (next
, '|', &next
);
520 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
524 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
529 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
533 fprintf (table
, " { ");
535 for (i
= 0; i
< size
- 1; i
++)
537 fprintf (table
, "%d, ", modifier
[i
].value
);
538 if (((i
+ 1) % 20) == 0)
539 fprintf (table
, "\n ");
542 fprintf (table
, "%d },\n", modifier
[i
].value
);
546 process_i386_opcode_modifier (FILE *table
, char *mod
)
548 char *str
, *next
, *last
;
549 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
551 /* Copy the default opcode modifier. */
552 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
554 if (strcmp (mod
, "0"))
556 last
= mod
+ strlen (mod
);
557 for (next
= mod
; next
&& next
< last
; )
559 str
= next_field (next
, '|', &next
);
561 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
564 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
568 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
569 int macro
, const char *indent
)
573 fprintf (table
, "{ { ");
575 for (i
= 0; i
< size
- 1; i
++)
577 fprintf (table
, "%d, ", types
[i
].value
);
578 if (((i
+ 1) % 20) == 0)
580 /* We need \\ for macro. */
582 fprintf (table
, "\\\n%s", indent
);
584 fprintf (table
, "\n%s", indent
);
588 fprintf (table
, "%d } }", types
[i
].value
);
592 process_i386_operand_type (FILE *table
, char *op
, int macro
,
595 char *str
, *next
, *last
;
596 bitfield types
[ARRAY_SIZE (operand_types
)];
598 /* Copy the default operand type. */
599 memcpy (types
, operand_types
, sizeof (types
));
601 if (strcmp (op
, "0"))
603 last
= op
+ strlen (op
);
604 for (next
= op
; next
&& next
< last
; )
606 str
= next_field (next
, '|', &next
);
608 set_bitfield (str
, types
, ARRAY_SIZE (types
));
611 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
616 process_i386_opcodes (FILE *table
)
621 char *str
, *p
, *last
;
622 char *name
, *operands
, *base_opcode
, *extension_opcode
;
624 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
626 filename
= "i386-opc.tbl";
627 fp
= fopen (filename
, "r");
630 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
633 fprintf (table
, "\n/* i386 opcode table. */\n\n");
634 fprintf (table
, "const template i386_optab[] =\n{\n");
638 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
643 p
= remove_leading_whitespaces (buf
);
646 str
= strstr (p
, "//");
650 /* Remove trailing white spaces. */
651 remove_trailing_whitespaces (p
);
656 fprintf (table
, "%s\n", p
);
664 last
= p
+ strlen (p
);
667 name
= next_field (p
, ',', &str
);
672 /* Find number of operands. */
673 operands
= next_field (str
, ',', &str
);
678 /* Find base_opcode. */
679 base_opcode
= next_field (str
, ',', &str
);
684 /* Find extension_opcode. */
685 extension_opcode
= next_field (str
, ',', &str
);
690 /* Find opcode_length. */
691 opcode_length
= next_field (str
, ',', &str
);
696 /* Find cpu_flags. */
697 cpu_flags
= next_field (str
, ',', &str
);
702 /* Find opcode_modifier. */
703 opcode_modifier
= next_field (str
, ',', &str
);
708 /* Remove the first {. */
709 str
= remove_leading_whitespaces (str
);
712 str
= remove_leading_whitespaces (str
+ 1);
716 /* There are at least "X}". */
720 /* Remove trailing white spaces and }. */
724 if (ISSPACE (str
[i
]) || str
[i
] == '}')
733 /* Find operand_types. */
734 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
738 operand_types
[i
] = NULL
;
742 operand_types
[i
] = next_field (str
, ',', &str
);
743 if (*operand_types
[i
] == '0')
746 operand_types
[i
] = NULL
;
751 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
752 name
, operands
, base_opcode
, extension_opcode
,
755 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
757 process_i386_opcode_modifier (table
, opcode_modifier
);
759 fprintf (table
, " { ");
761 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
763 if (operand_types
[i
] == NULL
764 || *operand_types
[i
] == '0')
767 process_i386_operand_type (table
, "0", 0, "\t ");
772 fprintf (table
, ",\n ");
774 process_i386_operand_type (table
, operand_types
[i
], 0,
777 fprintf (table
, " } },\n");
782 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
784 process_i386_cpu_flag (table
, "0", 0, ",", " ");
786 process_i386_opcode_modifier (table
, "0");
788 fprintf (table
, " { ");
789 process_i386_operand_type (table
, "0", 0, "\t ");
790 fprintf (table
, " } }\n");
792 fprintf (table
, "};\n");
796 process_i386_registers (FILE *table
)
800 char *str
, *p
, *last
;
801 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
803 filename
= "i386-reg.tbl";
804 fp
= fopen (filename
, "r");
806 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
809 fprintf (table
, "\n/* i386 register table. */\n\n");
810 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
814 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
819 p
= remove_leading_whitespaces (buf
);
822 str
= strstr (p
, "//");
826 /* Remove trailing white spaces. */
827 remove_trailing_whitespaces (p
);
832 fprintf (table
, "%s\n", p
);
840 last
= p
+ strlen (p
);
843 reg_name
= next_field (p
, ',', &str
);
849 reg_type
= next_field (str
, ',', &str
);
854 /* Find reg_flags. */
855 reg_flags
= next_field (str
, ',', &str
);
861 reg_num
= next_field (str
, ',', &str
);
863 fprintf (table
, " { \"%s\",\n ", reg_name
);
865 process_i386_operand_type (table
, reg_type
, 0, "\t");
867 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
872 fprintf (table
, "};\n");
874 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
878 process_i386_initializers (void)
881 FILE *fp
= fopen ("i386-init.h", "w");
885 fail (_("can't create i386-init.h, errno = %s\n"),
888 process_copyright (fp
);
890 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
892 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
893 init
= xstrdup (cpu_flag_init
[i
].init
);
894 process_i386_cpu_flag (fp
, init
, 1, "", " ");
898 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
900 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
901 init
= xstrdup (operand_type_init
[i
].init
);
902 process_i386_operand_type (fp
, init
, 1, " ");
910 /* Program options. */
911 #define OPTION_SRCDIR 200
913 struct option long_options
[] =
915 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
916 {"debug", no_argument
, NULL
, 'd'},
917 {"version", no_argument
, NULL
, 'V'},
918 {"help", no_argument
, NULL
, 'h'},
919 {0, no_argument
, NULL
, 0}
925 printf ("%s: version 1.0\n", program_name
);
930 usage (FILE * stream
, int status
)
932 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
938 main (int argc
, char **argv
)
940 extern int chdir (char *);
945 program_name
= *argv
;
946 xmalloc_set_program_name (program_name
);
948 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
973 if (chdir (srcdir
) != 0)
974 fail (_("unable to change directory to \"%s\", errno = %s\n"),
975 srcdir
, xstrerror (errno
));
977 /* Check the unused bitfield in i386_cpu_flags. */
979 c
= CpuNumOfBits
- CpuMax
- 1;
981 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
984 /* Check the unused bitfield in i386_operand_type. */
986 c
= OTNumOfBits
- OTMax
- 1;
988 fail (_("%d unused bits in i386_operand_type.\n"), c
);
991 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
994 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
995 sizeof (opcode_modifiers
[0]), compare
);
997 qsort (operand_types
, ARRAY_SIZE (operand_types
),
998 sizeof (operand_types
[0]), compare
);
1000 table
= fopen ("i386-tbl.h", "w");
1002 fail (_("can't create i386-tbl.h, errno = %s\n"),
1005 process_copyright (table
);
1007 process_i386_opcodes (table
);
1008 process_i386_registers (table
);
1009 process_i386_initializers ();