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
),
289 static bitfield operand_types
[] =
305 BITFIELD (BaseIndex
),
311 BITFIELD (InOutPortReg
),
312 BITFIELD (ShiftCount
),
320 BITFIELD (JumpAbsolute
),
329 compare (const void *x
, const void *y
)
331 const bitfield
*xp
= (const bitfield
*) x
;
332 const bitfield
*yp
= (const bitfield
*) y
;
333 return xp
->position
- yp
->position
;
337 fail (const char *message
, ...)
341 va_start (args
, message
);
342 fprintf (stderr
, _("%s: Error: "), program_name
);
343 vfprintf (stderr
, message
, args
);
349 process_copyright (FILE *fp
)
351 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
352 /* Copyright 2007 Free Software Foundation, Inc.\n\
354 This file is part of the GNU opcodes library.\n\
356 This library is free software; you can redistribute it and/or modify\n\
357 it under the terms of the GNU General Public License as published by\n\
358 the Free Software Foundation; either version 3, or (at your option)\n\
359 any later version.\n\
361 It is distributed in the hope that it will be useful, but WITHOUT\n\
362 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
363 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
364 License for more details.\n\
366 You should have received a copy of the GNU General Public License\n\
367 along with this program; if not, write to the Free Software\n\
368 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
369 MA 02110-1301, USA. */\n");
372 /* Remove leading white spaces. */
375 remove_leading_whitespaces (char *str
)
377 while (ISSPACE (*str
))
382 /* Remove trailing white spaces. */
385 remove_trailing_whitespaces (char *str
)
387 size_t last
= strlen (str
);
395 if (ISSPACE (str
[last
]))
403 /* Find next field separated by SEP and terminate it. Return a
404 pointer to the one after it. */
407 next_field (char *str
, char sep
, char **next
)
411 p
= remove_leading_whitespaces (str
);
412 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
415 remove_trailing_whitespaces (p
);
423 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
427 if (strcmp (f
, "CpuSledgehammer") == 0)
430 for (i
= 0; i
< size
; i
++)
431 if (strcasecmp (array
[i
].name
, f
) == 0)
437 printf ("Unknown bitfield: %s\n", f
);
442 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
443 int macro
, const char *comma
, const char *indent
)
447 fprintf (table
, "%s{ { ", indent
);
449 for (i
= 0; i
< size
- 1; i
++)
451 fprintf (table
, "%d, ", flags
[i
].value
);
452 if (((i
+ 1) % 20) == 0)
454 /* We need \\ for macro. */
456 fprintf (table
, " \\\n %s", indent
);
458 fprintf (table
, "\n %s", indent
);
462 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
466 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
467 const char *comma
, const char *indent
)
469 char *str
, *next
, *last
;
470 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
472 /* Copy the default cpu flags. */
473 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
475 if (strcasecmp (flag
, "unknown") == 0)
479 /* We turn on everything except for cpu64 in case of
480 CPU_UNKNOWN_FLAGS. */
481 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
482 if (flags
[i
].position
!= Cpu64
)
485 else if (strcmp (flag
, "0"))
487 last
= flag
+ strlen (flag
);
488 for (next
= flag
; next
&& next
< last
; )
490 str
= next_field (next
, '|', &next
);
492 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
496 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
501 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
505 fprintf (table
, " { ");
507 for (i
= 0; i
< size
- 1; i
++)
509 fprintf (table
, "%d, ", modifier
[i
].value
);
510 if (((i
+ 1) % 20) == 0)
511 fprintf (table
, "\n ");
514 fprintf (table
, "%d },\n", modifier
[i
].value
);
518 process_i386_opcode_modifier (FILE *table
, char *mod
)
520 char *str
, *next
, *last
;
521 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
523 /* Copy the default opcode modifier. */
524 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
526 if (strcmp (mod
, "0"))
528 last
= mod
+ strlen (mod
);
529 for (next
= mod
; next
&& next
< last
; )
531 str
= next_field (next
, '|', &next
);
533 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
536 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
540 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
541 int macro
, const char *indent
)
545 fprintf (table
, "{ { ");
547 for (i
= 0; i
< size
- 1; i
++)
549 fprintf (table
, "%d, ", types
[i
].value
);
550 if (((i
+ 1) % 20) == 0)
552 /* We need \\ for macro. */
554 fprintf (table
, "\\\n%s", indent
);
556 fprintf (table
, "\n%s", indent
);
560 fprintf (table
, "%d } }", types
[i
].value
);
564 process_i386_operand_type (FILE *table
, char *op
, int macro
,
567 char *str
, *next
, *last
;
568 bitfield types
[ARRAY_SIZE (operand_types
)];
570 /* Copy the default operand type. */
571 memcpy (types
, operand_types
, sizeof (types
));
573 if (strcmp (op
, "0"))
575 last
= op
+ strlen (op
);
576 for (next
= op
; next
&& next
< last
; )
578 str
= next_field (next
, '|', &next
);
580 set_bitfield (str
, types
, ARRAY_SIZE (types
));
583 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
588 process_i386_opcodes (FILE *table
)
590 FILE *fp
= fopen ("i386-opc.tbl", "r");
593 char *str
, *p
, *last
;
594 char *name
, *operands
, *base_opcode
, *extension_opcode
;
596 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
599 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
602 fprintf (table
, "\n/* i386 opcode table. */\n\n");
603 fprintf (table
, "const template i386_optab[] =\n{\n");
607 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
610 p
= remove_leading_whitespaces (buf
);
613 str
= strstr (p
, "//");
617 /* Remove trailing white spaces. */
618 remove_trailing_whitespaces (p
);
623 fprintf (table
, "%s\n", p
);
631 last
= p
+ strlen (p
);
634 name
= next_field (p
, ',', &str
);
639 /* Find number of operands. */
640 operands
= next_field (str
, ',', &str
);
645 /* Find base_opcode. */
646 base_opcode
= next_field (str
, ',', &str
);
651 /* Find extension_opcode. */
652 extension_opcode
= next_field (str
, ',', &str
);
657 /* Find opcode_length. */
658 opcode_length
= next_field (str
, ',', &str
);
663 /* Find cpu_flags. */
664 cpu_flags
= next_field (str
, ',', &str
);
669 /* Find opcode_modifier. */
670 opcode_modifier
= next_field (str
, ',', &str
);
675 /* Remove the first {. */
676 str
= remove_leading_whitespaces (str
);
679 str
= remove_leading_whitespaces (str
+ 1);
683 /* There are at least "X}". */
687 /* Remove trailing white spaces and }. */
691 if (ISSPACE (str
[i
]) || str
[i
] == '}')
700 /* Find operand_types. */
701 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
705 operand_types
[i
] = NULL
;
709 operand_types
[i
] = next_field (str
, ',', &str
);
710 if (*operand_types
[i
] == '0')
713 operand_types
[i
] = NULL
;
718 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
719 name
, operands
, base_opcode
, extension_opcode
,
722 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
724 process_i386_opcode_modifier (table
, opcode_modifier
);
726 fprintf (table
, " { ");
728 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
730 if (operand_types
[i
] == NULL
731 || *operand_types
[i
] == '0')
734 process_i386_operand_type (table
, "0", 0, "\t ");
739 fprintf (table
, ",\n ");
741 process_i386_operand_type (table
, operand_types
[i
], 0,
744 fprintf (table
, " } },\n");
749 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
751 process_i386_cpu_flag (table
, "0", 0, ",", " ");
753 process_i386_opcode_modifier (table
, "0");
755 fprintf (table
, " { ");
756 process_i386_operand_type (table
, "0", 0, "\t ");
757 fprintf (table
, " } }\n");
759 fprintf (table
, "};\n");
763 process_i386_registers (FILE *table
)
765 FILE *fp
= fopen ("i386-reg.tbl", "r");
767 char *str
, *p
, *last
;
768 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
771 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
774 fprintf (table
, "\n/* i386 register table. */\n\n");
775 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
779 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
782 p
= remove_leading_whitespaces (buf
);
785 str
= strstr (p
, "//");
789 /* Remove trailing white spaces. */
790 remove_trailing_whitespaces (p
);
795 fprintf (table
, "%s\n", p
);
803 last
= p
+ strlen (p
);
806 reg_name
= next_field (p
, ',', &str
);
812 reg_type
= next_field (str
, ',', &str
);
817 /* Find reg_flags. */
818 reg_flags
= next_field (str
, ',', &str
);
824 reg_num
= next_field (str
, ',', &str
);
826 fprintf (table
, " { \"%s\",\n ", reg_name
);
828 process_i386_operand_type (table
, reg_type
, 0, "\t");
830 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
835 fprintf (table
, "};\n");
837 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
841 process_i386_initializers (void)
844 FILE *fp
= fopen ("i386-init.h", "w");
848 fail (_("can't create i386-init.h, errno = %s\n"),
851 process_copyright (fp
);
853 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
855 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
856 init
= xstrdup (cpu_flag_init
[i
].init
);
857 process_i386_cpu_flag (fp
, init
, 1, "", " ");
861 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
863 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
864 init
= xstrdup (operand_type_init
[i
].init
);
865 process_i386_operand_type (fp
, init
, 1, " ");
873 /* Program options. */
874 #define OPTION_SRCDIR 200
876 struct option long_options
[] =
878 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
879 {"debug", no_argument
, NULL
, 'd'},
880 {"version", no_argument
, NULL
, 'V'},
881 {"help", no_argument
, NULL
, 'h'},
882 {0, no_argument
, NULL
, 0}
888 printf ("%s: version 1.0\n", program_name
);
893 usage (FILE * stream
, int status
)
895 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
901 main (int argc
, char **argv
)
903 extern int chdir (char *);
908 program_name
= *argv
;
909 xmalloc_set_program_name (program_name
);
911 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
936 if (chdir (srcdir
) != 0)
937 fail (_("unable to change directory to \"%s\", errno = %s\n"),
938 srcdir
, xstrerror (errno
));
940 /* Check the unused bitfield in i386_cpu_flags. */
942 c
= CpuNumOfBits
- CpuMax
- 1;
944 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
947 /* Check the unused bitfield in i386_operand_type. */
949 c
= OTNumOfBits
- OTMax
- 1;
951 fail (_("%d unused bits in i386_operand_type.\n"), c
);
954 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
957 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
958 sizeof (opcode_modifiers
[0]), compare
);
960 qsort (operand_types
, ARRAY_SIZE (operand_types
),
961 sizeof (operand_types
[0]), compare
);
963 table
= fopen ("i386-tbl.h", "w");
965 fail (_("can't create i386-tbl.h, errno = %s\n"),
968 process_copyright (table
);
970 process_i386_opcodes (table
);
971 process_i386_registers (table
);
972 process_i386_initializers ();