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
),
278 BITFIELD (RegKludge
),
279 BITFIELD (FirstXmm0
),
280 BITFIELD (ByteOkIntel
),
283 BITFIELD (AddrPrefixOp0
),
293 BITFIELD (ATTMnemonic
),
294 BITFIELD (ATTSyntax
),
295 BITFIELD (IntelSyntax
),
298 static bitfield operand_types
[] =
314 BITFIELD (BaseIndex
),
320 BITFIELD (InOutPortReg
),
321 BITFIELD (ShiftCount
),
329 BITFIELD (JumpAbsolute
),
340 BITFIELD (Unspecified
),
348 static const char *filename
;
351 compare (const void *x
, const void *y
)
353 const bitfield
*xp
= (const bitfield
*) x
;
354 const bitfield
*yp
= (const bitfield
*) y
;
355 return xp
->position
- yp
->position
;
359 fail (const char *message
, ...)
363 va_start (args
, message
);
364 fprintf (stderr
, _("%s: Error: "), program_name
);
365 vfprintf (stderr
, message
, args
);
371 process_copyright (FILE *fp
)
373 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
374 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
376 This file is part of the GNU opcodes library.\n\
378 This library is free software; you can redistribute it and/or modify\n\
379 it under the terms of the GNU General Public License as published by\n\
380 the Free Software Foundation; either version 3, or (at your option)\n\
381 any later version.\n\
383 It is distributed in the hope that it will be useful, but WITHOUT\n\
384 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
385 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
386 License for more details.\n\
388 You should have received a copy of the GNU General Public License\n\
389 along with this program; if not, write to the Free Software\n\
390 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
391 MA 02110-1301, USA. */\n");
394 /* Remove leading white spaces. */
397 remove_leading_whitespaces (char *str
)
399 while (ISSPACE (*str
))
404 /* Remove trailing white spaces. */
407 remove_trailing_whitespaces (char *str
)
409 size_t last
= strlen (str
);
417 if (ISSPACE (str
[last
]))
425 /* Find next field separated by SEP and terminate it. Return a
426 pointer to the one after it. */
429 next_field (char *str
, char sep
, char **next
)
433 p
= remove_leading_whitespaces (str
);
434 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
437 remove_trailing_whitespaces (p
);
445 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
449 if (strcmp (f
, "CpuSledgehammer") == 0)
451 else if (strcmp (f
, "Mmword") == 0)
453 else if (strcmp (f
, "Oword") == 0)
456 for (i
= 0; i
< size
; i
++)
457 if (strcasecmp (array
[i
].name
, f
) == 0)
463 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
467 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
468 int macro
, const char *comma
, const char *indent
)
472 fprintf (table
, "%s{ { ", indent
);
474 for (i
= 0; i
< size
- 1; i
++)
476 fprintf (table
, "%d, ", flags
[i
].value
);
477 if (((i
+ 1) % 20) == 0)
479 /* We need \\ for macro. */
481 fprintf (table
, " \\\n %s", indent
);
483 fprintf (table
, "\n %s", indent
);
487 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
491 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
492 const char *comma
, const char *indent
)
494 char *str
, *next
, *last
;
495 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
497 /* Copy the default cpu flags. */
498 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
500 if (strcasecmp (flag
, "unknown") == 0)
504 /* We turn on everything except for cpu64 in case of
505 CPU_UNKNOWN_FLAGS. */
506 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
507 if (flags
[i
].position
!= Cpu64
)
510 else if (strcmp (flag
, "0"))
512 last
= flag
+ strlen (flag
);
513 for (next
= flag
; next
&& next
< last
; )
515 str
= next_field (next
, '|', &next
);
517 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
521 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
526 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
530 fprintf (table
, " { ");
532 for (i
= 0; i
< size
- 1; i
++)
534 fprintf (table
, "%d, ", modifier
[i
].value
);
535 if (((i
+ 1) % 20) == 0)
536 fprintf (table
, "\n ");
539 fprintf (table
, "%d },\n", modifier
[i
].value
);
543 process_i386_opcode_modifier (FILE *table
, char *mod
)
545 char *str
, *next
, *last
;
546 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
548 /* Copy the default opcode modifier. */
549 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
551 if (strcmp (mod
, "0"))
553 last
= mod
+ strlen (mod
);
554 for (next
= mod
; next
&& next
< last
; )
556 str
= next_field (next
, '|', &next
);
558 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
561 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
565 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
566 int macro
, const char *indent
)
570 fprintf (table
, "{ { ");
572 for (i
= 0; i
< size
- 1; i
++)
574 fprintf (table
, "%d, ", types
[i
].value
);
575 if (((i
+ 1) % 20) == 0)
577 /* We need \\ for macro. */
579 fprintf (table
, "\\\n%s", indent
);
581 fprintf (table
, "\n%s", indent
);
585 fprintf (table
, "%d } }", types
[i
].value
);
589 process_i386_operand_type (FILE *table
, char *op
, int macro
,
592 char *str
, *next
, *last
;
593 bitfield types
[ARRAY_SIZE (operand_types
)];
595 /* Copy the default operand type. */
596 memcpy (types
, operand_types
, sizeof (types
));
598 if (strcmp (op
, "0"))
600 last
= op
+ strlen (op
);
601 for (next
= op
; next
&& next
< last
; )
603 str
= next_field (next
, '|', &next
);
605 set_bitfield (str
, types
, ARRAY_SIZE (types
));
608 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
613 process_i386_opcodes (FILE *table
)
618 char *str
, *p
, *last
;
619 char *name
, *operands
, *base_opcode
, *extension_opcode
;
621 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
623 filename
= "i386-opc.tbl";
624 fp
= fopen (filename
, "r");
627 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
630 fprintf (table
, "\n/* i386 opcode table. */\n\n");
631 fprintf (table
, "const template i386_optab[] =\n{\n");
635 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
640 p
= remove_leading_whitespaces (buf
);
643 str
= strstr (p
, "//");
647 /* Remove trailing white spaces. */
648 remove_trailing_whitespaces (p
);
653 fprintf (table
, "%s\n", p
);
661 last
= p
+ strlen (p
);
664 name
= next_field (p
, ',', &str
);
669 /* Find number of operands. */
670 operands
= next_field (str
, ',', &str
);
675 /* Find base_opcode. */
676 base_opcode
= next_field (str
, ',', &str
);
681 /* Find extension_opcode. */
682 extension_opcode
= next_field (str
, ',', &str
);
687 /* Find opcode_length. */
688 opcode_length
= next_field (str
, ',', &str
);
693 /* Find cpu_flags. */
694 cpu_flags
= next_field (str
, ',', &str
);
699 /* Find opcode_modifier. */
700 opcode_modifier
= next_field (str
, ',', &str
);
705 /* Remove the first {. */
706 str
= remove_leading_whitespaces (str
);
709 str
= remove_leading_whitespaces (str
+ 1);
713 /* There are at least "X}". */
717 /* Remove trailing white spaces and }. */
721 if (ISSPACE (str
[i
]) || str
[i
] == '}')
730 /* Find operand_types. */
731 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
735 operand_types
[i
] = NULL
;
739 operand_types
[i
] = next_field (str
, ',', &str
);
740 if (*operand_types
[i
] == '0')
743 operand_types
[i
] = NULL
;
748 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
749 name
, operands
, base_opcode
, extension_opcode
,
752 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
754 process_i386_opcode_modifier (table
, opcode_modifier
);
756 fprintf (table
, " { ");
758 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
760 if (operand_types
[i
] == NULL
761 || *operand_types
[i
] == '0')
764 process_i386_operand_type (table
, "0", 0, "\t ");
769 fprintf (table
, ",\n ");
771 process_i386_operand_type (table
, operand_types
[i
], 0,
774 fprintf (table
, " } },\n");
779 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
781 process_i386_cpu_flag (table
, "0", 0, ",", " ");
783 process_i386_opcode_modifier (table
, "0");
785 fprintf (table
, " { ");
786 process_i386_operand_type (table
, "0", 0, "\t ");
787 fprintf (table
, " } }\n");
789 fprintf (table
, "};\n");
793 process_i386_registers (FILE *table
)
797 char *str
, *p
, *last
;
798 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
800 filename
= "i386-reg.tbl";
801 fp
= fopen (filename
, "r");
803 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
806 fprintf (table
, "\n/* i386 register table. */\n\n");
807 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
811 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
816 p
= remove_leading_whitespaces (buf
);
819 str
= strstr (p
, "//");
823 /* Remove trailing white spaces. */
824 remove_trailing_whitespaces (p
);
829 fprintf (table
, "%s\n", p
);
837 last
= p
+ strlen (p
);
840 reg_name
= next_field (p
, ',', &str
);
846 reg_type
= next_field (str
, ',', &str
);
851 /* Find reg_flags. */
852 reg_flags
= next_field (str
, ',', &str
);
858 reg_num
= next_field (str
, ',', &str
);
860 fprintf (table
, " { \"%s\",\n ", reg_name
);
862 process_i386_operand_type (table
, reg_type
, 0, "\t");
864 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
869 fprintf (table
, "};\n");
871 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
875 process_i386_initializers (void)
878 FILE *fp
= fopen ("i386-init.h", "w");
882 fail (_("can't create i386-init.h, errno = %s\n"),
885 process_copyright (fp
);
887 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
889 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
890 init
= xstrdup (cpu_flag_init
[i
].init
);
891 process_i386_cpu_flag (fp
, init
, 1, "", " ");
895 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
897 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
898 init
= xstrdup (operand_type_init
[i
].init
);
899 process_i386_operand_type (fp
, init
, 1, " ");
907 /* Program options. */
908 #define OPTION_SRCDIR 200
910 struct option long_options
[] =
912 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
913 {"debug", no_argument
, NULL
, 'd'},
914 {"version", no_argument
, NULL
, 'V'},
915 {"help", no_argument
, NULL
, 'h'},
916 {0, no_argument
, NULL
, 0}
922 printf ("%s: version 1.0\n", program_name
);
927 usage (FILE * stream
, int status
)
929 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
935 main (int argc
, char **argv
)
937 extern int chdir (char *);
942 program_name
= *argv
;
943 xmalloc_set_program_name (program_name
);
945 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
970 if (chdir (srcdir
) != 0)
971 fail (_("unable to change directory to \"%s\", errno = %s\n"),
972 srcdir
, xstrerror (errno
));
974 /* Check the unused bitfield in i386_cpu_flags. */
976 c
= CpuNumOfBits
- CpuMax
- 1;
978 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
981 /* Check the unused bitfield in i386_operand_type. */
983 c
= OTNumOfBits
- OTMax
- 1;
985 fail (_("%d unused bits in i386_operand_type.\n"), c
);
988 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
991 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
992 sizeof (opcode_modifiers
[0]), compare
);
994 qsort (operand_types
, ARRAY_SIZE (operand_types
),
995 sizeof (operand_types
[0]), compare
);
997 table
= fopen ("i386-tbl.h", "w");
999 fail (_("can't create i386-tbl.h, errno = %s\n"),
1002 process_copyright (table
);
1004 process_i386_opcodes (table
);
1005 process_i386_registers (table
);
1006 process_i386_initializers ();