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|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
),
276 BITFIELD (CheckSize
),
284 BITFIELD (RegKludge
),
285 BITFIELD (FirstXmm0
),
286 BITFIELD (ByteOkIntel
),
289 BITFIELD (AddrPrefixOp0
),
299 BITFIELD (ATTMnemonic
),
300 BITFIELD (ATTSyntax
),
303 static bitfield operand_types
[] =
319 BITFIELD (BaseIndex
),
325 BITFIELD (InOutPortReg
),
326 BITFIELD (ShiftCount
),
334 BITFIELD (JumpAbsolute
),
343 static const char *filename
;
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, 2008 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 ("%s: %d: Unknown bitfield: %s\n",
455 filename
, lineno
, f
);
460 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
461 int macro
, const char *comma
, const char *indent
)
465 fprintf (table
, "%s{ { ", indent
);
467 for (i
= 0; i
< size
- 1; i
++)
469 fprintf (table
, "%d, ", flags
[i
].value
);
470 if (((i
+ 1) % 20) == 0)
472 /* We need \\ for macro. */
474 fprintf (table
, " \\\n %s", indent
);
476 fprintf (table
, "\n %s", indent
);
480 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
484 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
485 const char *comma
, const char *indent
)
487 char *str
, *next
, *last
;
488 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
490 /* Copy the default cpu flags. */
491 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
493 if (strcasecmp (flag
, "unknown") == 0)
497 /* We turn on everything except for cpu64 in case of
498 CPU_UNKNOWN_FLAGS. */
499 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
500 if (flags
[i
].position
!= Cpu64
)
503 else if (strcmp (flag
, "0"))
505 last
= flag
+ strlen (flag
);
506 for (next
= flag
; next
&& next
< last
; )
508 str
= next_field (next
, '|', &next
);
510 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
514 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
519 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
523 fprintf (table
, " { ");
525 for (i
= 0; i
< size
- 1; i
++)
527 fprintf (table
, "%d, ", modifier
[i
].value
);
528 if (((i
+ 1) % 20) == 0)
529 fprintf (table
, "\n ");
532 fprintf (table
, "%d },\n", modifier
[i
].value
);
536 process_i386_opcode_modifier (FILE *table
, char *mod
)
538 char *str
, *next
, *last
;
539 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
541 /* Copy the default opcode modifier. */
542 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
544 if (strcmp (mod
, "0"))
546 last
= mod
+ strlen (mod
);
547 for (next
= mod
; next
&& next
< last
; )
549 str
= next_field (next
, '|', &next
);
551 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
554 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
558 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
559 int macro
, const char *indent
)
563 fprintf (table
, "{ { ");
565 for (i
= 0; i
< size
- 1; i
++)
567 fprintf (table
, "%d, ", types
[i
].value
);
568 if (((i
+ 1) % 20) == 0)
570 /* We need \\ for macro. */
572 fprintf (table
, "\\\n%s", indent
);
574 fprintf (table
, "\n%s", indent
);
578 fprintf (table
, "%d } }", types
[i
].value
);
582 process_i386_operand_type (FILE *table
, char *op
, int macro
,
585 char *str
, *next
, *last
;
586 bitfield types
[ARRAY_SIZE (operand_types
)];
588 /* Copy the default operand type. */
589 memcpy (types
, operand_types
, sizeof (types
));
591 if (strcmp (op
, "0"))
593 last
= op
+ strlen (op
);
594 for (next
= op
; next
&& next
< last
; )
596 str
= next_field (next
, '|', &next
);
598 set_bitfield (str
, types
, ARRAY_SIZE (types
));
601 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
606 process_i386_opcodes (FILE *table
)
611 char *str
, *p
, *last
;
612 char *name
, *operands
, *base_opcode
, *extension_opcode
;
614 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
616 filename
= "i386-opc.tbl";
617 fp
= fopen (filename
, "r");
620 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
623 fprintf (table
, "\n/* i386 opcode table. */\n\n");
624 fprintf (table
, "const template i386_optab[] =\n{\n");
628 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
633 p
= remove_leading_whitespaces (buf
);
636 str
= strstr (p
, "//");
640 /* Remove trailing white spaces. */
641 remove_trailing_whitespaces (p
);
646 fprintf (table
, "%s\n", p
);
654 last
= p
+ strlen (p
);
657 name
= next_field (p
, ',', &str
);
662 /* Find number of operands. */
663 operands
= next_field (str
, ',', &str
);
668 /* Find base_opcode. */
669 base_opcode
= next_field (str
, ',', &str
);
674 /* Find extension_opcode. */
675 extension_opcode
= next_field (str
, ',', &str
);
680 /* Find opcode_length. */
681 opcode_length
= next_field (str
, ',', &str
);
686 /* Find cpu_flags. */
687 cpu_flags
= next_field (str
, ',', &str
);
692 /* Find opcode_modifier. */
693 opcode_modifier
= next_field (str
, ',', &str
);
698 /* Remove the first {. */
699 str
= remove_leading_whitespaces (str
);
702 str
= remove_leading_whitespaces (str
+ 1);
706 /* There are at least "X}". */
710 /* Remove trailing white spaces and }. */
714 if (ISSPACE (str
[i
]) || str
[i
] == '}')
723 /* Find operand_types. */
724 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
728 operand_types
[i
] = NULL
;
732 operand_types
[i
] = next_field (str
, ',', &str
);
733 if (*operand_types
[i
] == '0')
736 operand_types
[i
] = NULL
;
741 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
742 name
, operands
, base_opcode
, extension_opcode
,
745 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
747 process_i386_opcode_modifier (table
, opcode_modifier
);
749 fprintf (table
, " { ");
751 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
753 if (operand_types
[i
] == NULL
754 || *operand_types
[i
] == '0')
757 process_i386_operand_type (table
, "0", 0, "\t ");
762 fprintf (table
, ",\n ");
764 process_i386_operand_type (table
, operand_types
[i
], 0,
767 fprintf (table
, " } },\n");
772 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
774 process_i386_cpu_flag (table
, "0", 0, ",", " ");
776 process_i386_opcode_modifier (table
, "0");
778 fprintf (table
, " { ");
779 process_i386_operand_type (table
, "0", 0, "\t ");
780 fprintf (table
, " } }\n");
782 fprintf (table
, "};\n");
786 process_i386_registers (FILE *table
)
790 char *str
, *p
, *last
;
791 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
793 filename
= "i386-reg.tbl";
794 fp
= fopen (filename
, "r");
796 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
799 fprintf (table
, "\n/* i386 register table. */\n\n");
800 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
804 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
809 p
= remove_leading_whitespaces (buf
);
812 str
= strstr (p
, "//");
816 /* Remove trailing white spaces. */
817 remove_trailing_whitespaces (p
);
822 fprintf (table
, "%s\n", p
);
830 last
= p
+ strlen (p
);
833 reg_name
= next_field (p
, ',', &str
);
839 reg_type
= next_field (str
, ',', &str
);
844 /* Find reg_flags. */
845 reg_flags
= next_field (str
, ',', &str
);
851 reg_num
= next_field (str
, ',', &str
);
853 fprintf (table
, " { \"%s\",\n ", reg_name
);
855 process_i386_operand_type (table
, reg_type
, 0, "\t");
857 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
862 fprintf (table
, "};\n");
864 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
868 process_i386_initializers (void)
871 FILE *fp
= fopen ("i386-init.h", "w");
875 fail (_("can't create i386-init.h, errno = %s\n"),
878 process_copyright (fp
);
880 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
882 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
883 init
= xstrdup (cpu_flag_init
[i
].init
);
884 process_i386_cpu_flag (fp
, init
, 1, "", " ");
888 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
890 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
891 init
= xstrdup (operand_type_init
[i
].init
);
892 process_i386_operand_type (fp
, init
, 1, " ");
900 /* Program options. */
901 #define OPTION_SRCDIR 200
903 struct option long_options
[] =
905 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
906 {"debug", no_argument
, NULL
, 'd'},
907 {"version", no_argument
, NULL
, 'V'},
908 {"help", no_argument
, NULL
, 'h'},
909 {0, no_argument
, NULL
, 0}
915 printf ("%s: version 1.0\n", program_name
);
920 usage (FILE * stream
, int status
)
922 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
928 main (int argc
, char **argv
)
930 extern int chdir (char *);
935 program_name
= *argv
;
936 xmalloc_set_program_name (program_name
);
938 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
963 if (chdir (srcdir
) != 0)
964 fail (_("unable to change directory to \"%s\", errno = %s\n"),
965 srcdir
, xstrerror (errno
));
967 /* Check the unused bitfield in i386_cpu_flags. */
969 c
= CpuNumOfBits
- CpuMax
- 1;
971 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
974 /* Check the unused bitfield in i386_operand_type. */
976 c
= OTNumOfBits
- OTMax
- 1;
978 fail (_("%d unused bits in i386_operand_type.\n"), c
);
981 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
984 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
985 sizeof (opcode_modifiers
[0]), compare
);
987 qsort (operand_types
, ARRAY_SIZE (operand_types
),
988 sizeof (operand_types
[0]), compare
);
990 table
= fopen ("i386-tbl.h", "w");
992 fail (_("can't create i386-tbl.h, errno = %s\n"),
995 process_copyright (table
);
997 process_i386_opcodes (table
);
998 process_i386_registers (table
);
999 process_i386_initializers ();