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
),
279 BITFIELD (FirstXmm0
),
290 static bitfield operand_types
[] =
306 BITFIELD (BaseIndex
),
312 BITFIELD (InOutPortReg
),
313 BITFIELD (ShiftCount
),
321 BITFIELD (JumpAbsolute
),
330 compare (const void *x
, const void *y
)
332 const bitfield
*xp
= (const bitfield
*) x
;
333 const bitfield
*yp
= (const bitfield
*) y
;
334 return xp
->position
- yp
->position
;
338 fail (const char *message
, ...)
342 va_start (args
, message
);
343 fprintf (stderr
, _("%s: Error: "), program_name
);
344 vfprintf (stderr
, message
, args
);
350 process_copyright (FILE *fp
)
352 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
353 /* Copyright 2007 Free Software Foundation, Inc.\n\
355 This file is part of the GNU opcodes library.\n\
357 This library is free software; you can redistribute it and/or modify\n\
358 it under the terms of the GNU General Public License as published by\n\
359 the Free Software Foundation; either version 3, or (at your option)\n\
360 any later version.\n\
362 It is distributed in the hope that it will be useful, but WITHOUT\n\
363 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
364 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
365 License for more details.\n\
367 You should have received a copy of the GNU General Public License\n\
368 along with this program; if not, write to the Free Software\n\
369 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
370 MA 02110-1301, USA. */\n");
373 /* Remove leading white spaces. */
376 remove_leading_whitespaces (char *str
)
378 while (ISSPACE (*str
))
383 /* Remove trailing white spaces. */
386 remove_trailing_whitespaces (char *str
)
388 size_t last
= strlen (str
);
396 if (ISSPACE (str
[last
]))
404 /* Find next field separated by SEP and terminate it. Return a
405 pointer to the one after it. */
408 next_field (char *str
, char sep
, char **next
)
412 p
= remove_leading_whitespaces (str
);
413 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
416 remove_trailing_whitespaces (p
);
424 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
428 if (strcmp (f
, "CpuSledgehammer") == 0)
431 for (i
= 0; i
< size
; i
++)
432 if (strcasecmp (array
[i
].name
, f
) == 0)
438 printf ("Unknown bitfield: %s\n", f
);
443 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
444 int macro
, const char *comma
, const char *indent
)
448 fprintf (table
, "%s{ { ", indent
);
450 for (i
= 0; i
< size
- 1; i
++)
452 fprintf (table
, "%d, ", flags
[i
].value
);
453 if (((i
+ 1) % 20) == 0)
455 /* We need \\ for macro. */
457 fprintf (table
, " \\\n %s", indent
);
459 fprintf (table
, "\n %s", indent
);
463 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
467 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
468 const char *comma
, const char *indent
)
470 char *str
, *next
, *last
;
471 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
473 /* Copy the default cpu flags. */
474 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
476 if (strcasecmp (flag
, "unknown") == 0)
480 /* We turn on everything except for cpu64 in case of
481 CPU_UNKNOWN_FLAGS. */
482 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
483 if (flags
[i
].position
!= Cpu64
)
486 else if (strcmp (flag
, "0"))
488 last
= flag
+ strlen (flag
);
489 for (next
= flag
; next
&& next
< last
; )
491 str
= next_field (next
, '|', &next
);
493 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
497 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
502 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
506 fprintf (table
, " { ");
508 for (i
= 0; i
< size
- 1; i
++)
510 fprintf (table
, "%d, ", modifier
[i
].value
);
511 if (((i
+ 1) % 20) == 0)
512 fprintf (table
, "\n ");
515 fprintf (table
, "%d },\n", modifier
[i
].value
);
519 process_i386_opcode_modifier (FILE *table
, char *mod
)
521 char *str
, *next
, *last
;
522 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
524 /* Copy the default opcode modifier. */
525 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
527 if (strcmp (mod
, "0"))
529 last
= mod
+ strlen (mod
);
530 for (next
= mod
; next
&& next
< last
; )
532 str
= next_field (next
, '|', &next
);
534 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
537 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
541 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
542 int macro
, const char *indent
)
546 fprintf (table
, "{ { ");
548 for (i
= 0; i
< size
- 1; i
++)
550 fprintf (table
, "%d, ", types
[i
].value
);
551 if (((i
+ 1) % 20) == 0)
553 /* We need \\ for macro. */
555 fprintf (table
, "\\\n%s", indent
);
557 fprintf (table
, "\n%s", indent
);
561 fprintf (table
, "%d } }", types
[i
].value
);
565 process_i386_operand_type (FILE *table
, char *op
, int macro
,
568 char *str
, *next
, *last
;
569 bitfield types
[ARRAY_SIZE (operand_types
)];
571 /* Copy the default operand type. */
572 memcpy (types
, operand_types
, sizeof (types
));
574 if (strcmp (op
, "0"))
576 last
= op
+ strlen (op
);
577 for (next
= op
; next
&& next
< last
; )
579 str
= next_field (next
, '|', &next
);
581 set_bitfield (str
, types
, ARRAY_SIZE (types
));
584 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
589 process_i386_opcodes (FILE *table
)
591 FILE *fp
= fopen ("i386-opc.tbl", "r");
594 char *str
, *p
, *last
;
595 char *name
, *operands
, *base_opcode
, *extension_opcode
;
597 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
600 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
603 fprintf (table
, "\n/* i386 opcode table. */\n\n");
604 fprintf (table
, "const template i386_optab[] =\n{\n");
608 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
611 p
= remove_leading_whitespaces (buf
);
614 str
= strstr (p
, "//");
618 /* Remove trailing white spaces. */
619 remove_trailing_whitespaces (p
);
624 fprintf (table
, "%s\n", p
);
632 last
= p
+ strlen (p
);
635 name
= next_field (p
, ',', &str
);
640 /* Find number of operands. */
641 operands
= next_field (str
, ',', &str
);
646 /* Find base_opcode. */
647 base_opcode
= next_field (str
, ',', &str
);
652 /* Find extension_opcode. */
653 extension_opcode
= next_field (str
, ',', &str
);
658 /* Find opcode_length. */
659 opcode_length
= next_field (str
, ',', &str
);
664 /* Find cpu_flags. */
665 cpu_flags
= next_field (str
, ',', &str
);
670 /* Find opcode_modifier. */
671 opcode_modifier
= next_field (str
, ',', &str
);
676 /* Remove the first {. */
677 str
= remove_leading_whitespaces (str
);
680 str
= remove_leading_whitespaces (str
+ 1);
684 /* There are at least "X}". */
688 /* Remove trailing white spaces and }. */
692 if (ISSPACE (str
[i
]) || str
[i
] == '}')
701 /* Find operand_types. */
702 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
706 operand_types
[i
] = NULL
;
710 operand_types
[i
] = next_field (str
, ',', &str
);
711 if (*operand_types
[i
] == '0')
714 operand_types
[i
] = NULL
;
719 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
720 name
, operands
, base_opcode
, extension_opcode
,
723 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
725 process_i386_opcode_modifier (table
, opcode_modifier
);
727 fprintf (table
, " { ");
729 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
731 if (operand_types
[i
] == NULL
732 || *operand_types
[i
] == '0')
735 process_i386_operand_type (table
, "0", 0, "\t ");
740 fprintf (table
, ",\n ");
742 process_i386_operand_type (table
, operand_types
[i
], 0,
745 fprintf (table
, " } },\n");
750 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
752 process_i386_cpu_flag (table
, "0", 0, ",", " ");
754 process_i386_opcode_modifier (table
, "0");
756 fprintf (table
, " { ");
757 process_i386_operand_type (table
, "0", 0, "\t ");
758 fprintf (table
, " } }\n");
760 fprintf (table
, "};\n");
764 process_i386_registers (FILE *table
)
766 FILE *fp
= fopen ("i386-reg.tbl", "r");
768 char *str
, *p
, *last
;
769 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
772 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
775 fprintf (table
, "\n/* i386 register table. */\n\n");
776 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
780 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
783 p
= remove_leading_whitespaces (buf
);
786 str
= strstr (p
, "//");
790 /* Remove trailing white spaces. */
791 remove_trailing_whitespaces (p
);
796 fprintf (table
, "%s\n", p
);
804 last
= p
+ strlen (p
);
807 reg_name
= next_field (p
, ',', &str
);
813 reg_type
= next_field (str
, ',', &str
);
818 /* Find reg_flags. */
819 reg_flags
= next_field (str
, ',', &str
);
825 reg_num
= next_field (str
, ',', &str
);
827 fprintf (table
, " { \"%s\",\n ", reg_name
);
829 process_i386_operand_type (table
, reg_type
, 0, "\t");
831 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
836 fprintf (table
, "};\n");
838 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
842 process_i386_initializers (void)
845 FILE *fp
= fopen ("i386-init.h", "w");
849 fail (_("can't create i386-init.h, errno = %s\n"),
852 process_copyright (fp
);
854 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
856 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
857 init
= xstrdup (cpu_flag_init
[i
].init
);
858 process_i386_cpu_flag (fp
, init
, 1, "", " ");
862 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
864 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
865 init
= xstrdup (operand_type_init
[i
].init
);
866 process_i386_operand_type (fp
, init
, 1, " ");
874 /* Program options. */
875 #define OPTION_SRCDIR 200
877 struct option long_options
[] =
879 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
880 {"debug", no_argument
, NULL
, 'd'},
881 {"version", no_argument
, NULL
, 'V'},
882 {"help", no_argument
, NULL
, 'h'},
883 {0, no_argument
, NULL
, 0}
889 printf ("%s: version 1.0\n", program_name
);
894 usage (FILE * stream
, int status
)
896 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
902 main (int argc
, char **argv
)
904 extern int chdir (char *);
909 program_name
= *argv
;
910 xmalloc_set_program_name (program_name
);
912 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
937 if (chdir (srcdir
) != 0)
938 fail (_("unable to change directory to \"%s\", errno = %s\n"),
939 srcdir
, xstrerror (errno
));
941 /* Check the unused bitfield in i386_cpu_flags. */
943 c
= CpuNumOfBits
- CpuMax
- 1;
945 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
948 /* Check the unused bitfield in i386_operand_type. */
950 c
= OTNumOfBits
- OTMax
- 1;
952 fail (_("%d unused bits in i386_operand_type.\n"), c
);
955 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
958 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
959 sizeof (opcode_modifiers
[0]), compare
);
961 qsort (operand_types
, ARRAY_SIZE (operand_types
),
962 sizeof (operand_types
[0]), compare
);
964 table
= fopen ("i386-tbl.h", "w");
966 fail (_("can't create i386-tbl.h, errno = %s\n"),
969 process_copyright (table
);
971 process_i386_opcodes (table
);
972 process_i386_registers (table
);
973 process_i386_initializers ();