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" },
113 static initializer operand_type_init
[] =
115 { "OPERAND_TYPE_NONE",
117 { "OPERAND_TYPE_REG8",
119 { "OPERAND_TYPE_REG16",
121 { "OPERAND_TYPE_REG32",
123 { "OPERAND_TYPE_REG64",
125 { "OPERAND_TYPE_IMM1",
127 { "OPERAND_TYPE_IMM8",
129 { "OPERAND_TYPE_IMM8S",
131 { "OPERAND_TYPE_IMM16",
133 { "OPERAND_TYPE_IMM32",
135 { "OPERAND_TYPE_IMM32S",
137 { "OPERAND_TYPE_IMM64",
139 { "OPERAND_TYPE_BASEINDEX",
141 { "OPERAND_TYPE_DISP8",
143 { "OPERAND_TYPE_DISP16",
145 { "OPERAND_TYPE_DISP32",
147 { "OPERAND_TYPE_DISP32S",
149 { "OPERAND_TYPE_DISP64",
151 { "OPERAND_TYPE_INOUTPORTREG",
153 { "OPERAND_TYPE_SHIFTCOUNT",
155 { "OPERAND_TYPE_CONTROL",
157 { "OPERAND_TYPE_TEST",
159 { "OPERAND_TYPE_DEBUG",
161 { "OPERAND_TYPE_FLOATREG",
163 { "OPERAND_TYPE_FLOATACC",
165 { "OPERAND_TYPE_SREG2",
167 { "OPERAND_TYPE_SREG3",
169 { "OPERAND_TYPE_ACC",
171 { "OPERAND_TYPE_JUMPABSOLUTE",
173 { "OPERAND_TYPE_REGMMX",
175 { "OPERAND_TYPE_REGXMM",
177 { "OPERAND_TYPE_ESSEG",
179 { "OPERAND_TYPE_ACC32",
181 { "OPERAND_TYPE_ACC64",
183 { "OPERAND_TYPE_REG16_INOUTPORTREG",
184 "Reg16|InOutPortReg" },
185 { "OPERAND_TYPE_DISP16_32",
187 { "OPERAND_TYPE_ANYDISP",
188 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
189 { "OPERAND_TYPE_IMM16_32",
191 { "OPERAND_TYPE_IMM16_32S",
193 { "OPERAND_TYPE_IMM16_32_32S",
194 "Imm16|Imm32|Imm32S" },
195 { "OPERAND_TYPE_IMM32_32S_DISP32",
196 "Imm32|Imm32S|Disp32" },
197 { "OPERAND_TYPE_IMM64_DISP64",
199 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
200 "Imm32|Imm32S|Imm64|Disp32" },
201 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
202 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
205 typedef struct bitfield
212 #define BITFIELD(n) { n, 0, #n }
214 static bitfield cpu_flags
[] =
231 BITFIELD (CpuSSE4_1
),
232 BITFIELD (CpuSSE4_2
),
235 BITFIELD (Cpu3dnowA
),
236 BITFIELD (CpuPadLock
),
244 BITFIELD (CpuUnused
),
248 static bitfield opcode_modifiers
[] =
253 BITFIELD (ShortForm
),
255 BITFIELD (JumpDword
),
257 BITFIELD (JumpInterSegment
),
264 BITFIELD (IgnoreSize
),
265 BITFIELD (DefaultSize
),
274 BITFIELD (RegKludge
),
282 static bitfield operand_types
[] =
298 BITFIELD (BaseIndex
),
304 BITFIELD (InOutPortReg
),
305 BITFIELD (ShiftCount
),
313 BITFIELD (JumpAbsolute
),
322 compare (const void *x
, const void *y
)
324 const bitfield
*xp
= (const bitfield
*) x
;
325 const bitfield
*yp
= (const bitfield
*) y
;
326 return xp
->position
- yp
->position
;
330 fail (const char *message
, ...)
334 va_start (args
, message
);
335 fprintf (stderr
, _("%s: Error: "), program_name
);
336 vfprintf (stderr
, message
, args
);
342 process_copyright (FILE *fp
)
344 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
345 /* Copyright 2007 Free Software Foundation, Inc.\n\
347 This file is part of the GNU opcodes library.\n\
349 This library is free software; you can redistribute it and/or modify\n\
350 it under the terms of the GNU General Public License as published by\n\
351 the Free Software Foundation; either version 3, or (at your option)\n\
352 any later version.\n\
354 It is distributed in the hope that it will be useful, but WITHOUT\n\
355 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
356 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
357 License for more details.\n\
359 You should have received a copy of the GNU General Public License\n\
360 along with this program; if not, write to the Free Software\n\
361 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
362 MA 02110-1301, USA. */\n");
365 /* Remove leading white spaces. */
368 remove_leading_whitespaces (char *str
)
370 while (ISSPACE (*str
))
375 /* Remove trailing white spaces. */
378 remove_trailing_whitespaces (char *str
)
380 size_t last
= strlen (str
);
388 if (ISSPACE (str
[last
]))
396 /* Find next field separated by SEP and terminate it. Return a
397 pointer to the one after it. */
400 next_field (char *str
, char sep
, char **next
)
404 p
= remove_leading_whitespaces (str
);
405 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
408 remove_trailing_whitespaces (p
);
416 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
420 if (strcmp (f
, "CpuSledgehammer") == 0)
423 for (i
= 0; i
< size
; i
++)
424 if (strcasecmp (array
[i
].name
, f
) == 0)
430 printf ("Unknown bitfield: %s\n", f
);
435 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
436 int macro
, const char *comma
, const char *indent
)
440 fprintf (table
, "%s{ { ", indent
);
442 for (i
= 0; i
< size
- 1; i
++)
444 fprintf (table
, "%d, ", flags
[i
].value
);
445 if (((i
+ 1) % 20) == 0)
447 /* We need \\ for macro. */
449 fprintf (table
, " \\\n %s", indent
);
451 fprintf (table
, "\n %s", indent
);
455 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
459 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
460 const char *comma
, const char *indent
)
462 char *str
, *next
, *last
;
463 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
465 /* Copy the default cpu flags. */
466 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
468 if (strcasecmp (flag
, "unknown") == 0)
472 /* We turn on everything except for cpu64 in case of
473 CPU_UNKNOWN_FLAGS. */
474 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
475 if (flags
[i
].position
!= Cpu64
)
478 else if (strcmp (flag
, "0"))
480 last
= flag
+ strlen (flag
);
481 for (next
= flag
; next
&& next
< last
; )
483 str
= next_field (next
, '|', &next
);
485 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
489 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
494 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
498 fprintf (table
, " { ");
500 for (i
= 0; i
< size
- 1; i
++)
502 fprintf (table
, "%d, ", modifier
[i
].value
);
503 if (((i
+ 1) % 20) == 0)
504 fprintf (table
, "\n ");
507 fprintf (table
, "%d },\n", modifier
[i
].value
);
511 process_i386_opcode_modifier (FILE *table
, char *mod
)
513 char *str
, *next
, *last
;
514 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
516 /* Copy the default opcode modifier. */
517 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
519 if (strcmp (mod
, "0"))
521 last
= mod
+ strlen (mod
);
522 for (next
= mod
; next
&& next
< last
; )
524 str
= next_field (next
, '|', &next
);
526 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
529 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
533 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
534 int macro
, const char *indent
)
538 fprintf (table
, "{ { ");
540 for (i
= 0; i
< size
- 1; i
++)
542 fprintf (table
, "%d, ", types
[i
].value
);
543 if (((i
+ 1) % 20) == 0)
545 /* We need \\ for macro. */
547 fprintf (table
, "\\\n%s", indent
);
549 fprintf (table
, "\n%s", indent
);
553 fprintf (table
, "%d } }", types
[i
].value
);
557 process_i386_operand_type (FILE *table
, char *op
, int macro
,
560 char *str
, *next
, *last
;
561 bitfield types
[ARRAY_SIZE (operand_types
)];
563 /* Copy the default operand type. */
564 memcpy (types
, operand_types
, sizeof (types
));
566 if (strcmp (op
, "0"))
568 last
= op
+ strlen (op
);
569 for (next
= op
; next
&& next
< last
; )
571 str
= next_field (next
, '|', &next
);
573 set_bitfield (str
, types
, ARRAY_SIZE (types
));
576 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
581 process_i386_opcodes (FILE *table
)
583 FILE *fp
= fopen ("i386-opc.tbl", "r");
586 char *str
, *p
, *last
;
587 char *name
, *operands
, *base_opcode
, *extension_opcode
;
588 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
591 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
594 fprintf (table
, "\n/* i386 opcode table. */\n\n");
595 fprintf (table
, "const template i386_optab[] =\n{\n");
599 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
602 p
= remove_leading_whitespaces (buf
);
605 str
= strstr (p
, "//");
609 /* Remove trailing white spaces. */
610 remove_trailing_whitespaces (p
);
615 fprintf (table
, "%s\n", p
);
623 last
= p
+ strlen (p
);
626 name
= next_field (p
, ',', &str
);
631 /* Find number of operands. */
632 operands
= next_field (str
, ',', &str
);
637 /* Find base_opcode. */
638 base_opcode
= next_field (str
, ',', &str
);
643 /* Find extension_opcode. */
644 extension_opcode
= next_field (str
, ',', &str
);
649 /* Find cpu_flags. */
650 cpu_flags
= next_field (str
, ',', &str
);
655 /* Find opcode_modifier. */
656 opcode_modifier
= next_field (str
, ',', &str
);
661 /* Remove the first {. */
662 str
= remove_leading_whitespaces (str
);
665 str
= remove_leading_whitespaces (str
+ 1);
669 /* There are at least "X}". */
673 /* Remove trailing white spaces and }. */
677 if (ISSPACE (str
[i
]) || str
[i
] == '}')
686 /* Find operand_types. */
687 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
691 operand_types
[i
] = NULL
;
695 operand_types
[i
] = next_field (str
, ',', &str
);
696 if (*operand_types
[i
] == '0')
699 operand_types
[i
] = NULL
;
704 fprintf (table
, " { \"%s\", %s, %s, %s,\n",
705 name
, operands
, base_opcode
, extension_opcode
);
707 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
709 process_i386_opcode_modifier (table
, opcode_modifier
);
711 fprintf (table
, " { ");
713 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
715 if (operand_types
[i
] == NULL
716 || *operand_types
[i
] == '0')
719 process_i386_operand_type (table
, "0", 0, "\t ");
724 fprintf (table
, ",\n ");
726 process_i386_operand_type (table
, operand_types
[i
], 0,
729 fprintf (table
, " } },\n");
734 fprintf (table
, " { NULL, 0, 0, 0,\n");
736 process_i386_cpu_flag (table
, "0", 0, ",", " ");
738 process_i386_opcode_modifier (table
, "0");
740 fprintf (table
, " { ");
741 process_i386_operand_type (table
, "0", 0, "\t ");
742 fprintf (table
, " } }\n");
744 fprintf (table
, "};\n");
748 process_i386_registers (FILE *table
)
750 FILE *fp
= fopen ("i386-reg.tbl", "r");
752 char *str
, *p
, *last
;
753 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
756 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
759 fprintf (table
, "\n/* i386 register table. */\n\n");
760 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
764 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
767 p
= remove_leading_whitespaces (buf
);
770 str
= strstr (p
, "//");
774 /* Remove trailing white spaces. */
775 remove_trailing_whitespaces (p
);
780 fprintf (table
, "%s\n", p
);
788 last
= p
+ strlen (p
);
791 reg_name
= next_field (p
, ',', &str
);
797 reg_type
= next_field (str
, ',', &str
);
802 /* Find reg_flags. */
803 reg_flags
= next_field (str
, ',', &str
);
809 reg_num
= next_field (str
, ',', &str
);
811 fprintf (table
, " { \"%s\",\n ", reg_name
);
813 process_i386_operand_type (table
, reg_type
, 0, "\t");
815 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
820 fprintf (table
, "};\n");
822 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
826 process_i386_initializers (void)
829 FILE *fp
= fopen ("i386-init.h", "w");
833 fail (_("can't create i386-init.h, errno = %s\n"),
836 process_copyright (fp
);
838 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
840 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
841 init
= xstrdup (cpu_flag_init
[i
].init
);
842 process_i386_cpu_flag (fp
, init
, 1, "", " ");
846 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
848 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
849 init
= xstrdup (operand_type_init
[i
].init
);
850 process_i386_operand_type (fp
, init
, 1, " ");
858 /* Program options. */
859 #define OPTION_SRCDIR 200
861 struct option long_options
[] =
863 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
864 {"debug", no_argument
, NULL
, 'd'},
865 {"version", no_argument
, NULL
, 'V'},
866 {"help", no_argument
, NULL
, 'h'},
867 {0, no_argument
, NULL
, 0}
873 printf ("%s: version 1.0\n", program_name
);
878 usage (FILE * stream
, int status
)
880 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
886 main (int argc
, char **argv
)
888 extern int chdir (char *);
893 program_name
= *argv
;
894 xmalloc_set_program_name (program_name
);
896 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
921 if (chdir (srcdir
) != 0)
922 fail (_("unable to change directory to \"%s\", errno = %s\n"),
923 srcdir
, xstrerror (errno
));
925 /* Check the unused bitfield in i386_cpu_flags. */
927 unused
= CpuNumOfBits
- CpuMax
- 1;
929 fail (_("%d unused bits in i386_cpu_flags.\n"), unused
);
932 /* Check the unused bitfield in i386_operand_type. */
934 unused
= OTNumOfBits
- OTMax
- 1;
936 fail (_("%d unused bits in i386_operand_type.\n"), unused
);
939 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
942 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
943 sizeof (opcode_modifiers
[0]), compare
);
945 qsort (operand_types
, ARRAY_SIZE (operand_types
),
946 sizeof (operand_types
[0]), compare
);
948 table
= fopen ("i386-tbl.h", "w");
950 fail (_("can't create i386-tbl.h, errno = %s\n"),
953 process_copyright (table
);
955 process_i386_opcodes (table
);
956 process_i386_registers (table
);
957 process_i386_initializers ();