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
),
280 BITFIELD (ByteOkIntel
),
283 BITFIELD (AddrPrefixOp0
),
294 static bitfield operand_types
[] =
310 BITFIELD (BaseIndex
),
316 BITFIELD (InOutPortReg
),
317 BITFIELD (ShiftCount
),
325 BITFIELD (JumpAbsolute
),
334 compare (const void *x
, const void *y
)
336 const bitfield
*xp
= (const bitfield
*) x
;
337 const bitfield
*yp
= (const bitfield
*) y
;
338 return xp
->position
- yp
->position
;
342 fail (const char *message
, ...)
346 va_start (args
, message
);
347 fprintf (stderr
, _("%s: Error: "), program_name
);
348 vfprintf (stderr
, message
, args
);
354 process_copyright (FILE *fp
)
356 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
357 /* Copyright 2007 Free Software Foundation, Inc.\n\
359 This file is part of the GNU opcodes library.\n\
361 This library is free software; you can redistribute it and/or modify\n\
362 it under the terms of the GNU General Public License as published by\n\
363 the Free Software Foundation; either version 3, or (at your option)\n\
364 any later version.\n\
366 It is distributed in the hope that it will be useful, but WITHOUT\n\
367 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
368 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
369 License for more details.\n\
371 You should have received a copy of the GNU General Public License\n\
372 along with this program; if not, write to the Free Software\n\
373 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
374 MA 02110-1301, USA. */\n");
377 /* Remove leading white spaces. */
380 remove_leading_whitespaces (char *str
)
382 while (ISSPACE (*str
))
387 /* Remove trailing white spaces. */
390 remove_trailing_whitespaces (char *str
)
392 size_t last
= strlen (str
);
400 if (ISSPACE (str
[last
]))
408 /* Find next field separated by SEP and terminate it. Return a
409 pointer to the one after it. */
412 next_field (char *str
, char sep
, char **next
)
416 p
= remove_leading_whitespaces (str
);
417 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
420 remove_trailing_whitespaces (p
);
428 set_bitfield (const char *f
, bitfield
*array
, unsigned int size
)
432 if (strcmp (f
, "CpuSledgehammer") == 0)
435 for (i
= 0; i
< size
; i
++)
436 if (strcasecmp (array
[i
].name
, f
) == 0)
442 printf ("Unknown bitfield: %s\n", f
);
447 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
448 int macro
, const char *comma
, const char *indent
)
452 fprintf (table
, "%s{ { ", indent
);
454 for (i
= 0; i
< size
- 1; i
++)
456 fprintf (table
, "%d, ", flags
[i
].value
);
457 if (((i
+ 1) % 20) == 0)
459 /* We need \\ for macro. */
461 fprintf (table
, " \\\n %s", indent
);
463 fprintf (table
, "\n %s", indent
);
467 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
471 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
472 const char *comma
, const char *indent
)
474 char *str
, *next
, *last
;
475 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
477 /* Copy the default cpu flags. */
478 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
480 if (strcasecmp (flag
, "unknown") == 0)
484 /* We turn on everything except for cpu64 in case of
485 CPU_UNKNOWN_FLAGS. */
486 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
487 if (flags
[i
].position
!= Cpu64
)
490 else if (strcmp (flag
, "0"))
492 last
= flag
+ strlen (flag
);
493 for (next
= flag
; next
&& next
< last
; )
495 str
= next_field (next
, '|', &next
);
497 set_bitfield (str
, flags
, ARRAY_SIZE (flags
));
501 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
506 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
510 fprintf (table
, " { ");
512 for (i
= 0; i
< size
- 1; i
++)
514 fprintf (table
, "%d, ", modifier
[i
].value
);
515 if (((i
+ 1) % 20) == 0)
516 fprintf (table
, "\n ");
519 fprintf (table
, "%d },\n", modifier
[i
].value
);
523 process_i386_opcode_modifier (FILE *table
, char *mod
)
525 char *str
, *next
, *last
;
526 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
528 /* Copy the default opcode modifier. */
529 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
531 if (strcmp (mod
, "0"))
533 last
= mod
+ strlen (mod
);
534 for (next
= mod
; next
&& next
< last
; )
536 str
= next_field (next
, '|', &next
);
538 set_bitfield (str
, modifiers
, ARRAY_SIZE (modifiers
));
541 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
545 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
546 int macro
, const char *indent
)
550 fprintf (table
, "{ { ");
552 for (i
= 0; i
< size
- 1; i
++)
554 fprintf (table
, "%d, ", types
[i
].value
);
555 if (((i
+ 1) % 20) == 0)
557 /* We need \\ for macro. */
559 fprintf (table
, "\\\n%s", indent
);
561 fprintf (table
, "\n%s", indent
);
565 fprintf (table
, "%d } }", types
[i
].value
);
569 process_i386_operand_type (FILE *table
, char *op
, int macro
,
572 char *str
, *next
, *last
;
573 bitfield types
[ARRAY_SIZE (operand_types
)];
575 /* Copy the default operand type. */
576 memcpy (types
, operand_types
, sizeof (types
));
578 if (strcmp (op
, "0"))
580 last
= op
+ strlen (op
);
581 for (next
= op
; next
&& next
< last
; )
583 str
= next_field (next
, '|', &next
);
585 set_bitfield (str
, types
, ARRAY_SIZE (types
));
588 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
593 process_i386_opcodes (FILE *table
)
595 FILE *fp
= fopen ("i386-opc.tbl", "r");
598 char *str
, *p
, *last
;
599 char *name
, *operands
, *base_opcode
, *extension_opcode
;
601 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
604 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
607 fprintf (table
, "\n/* i386 opcode table. */\n\n");
608 fprintf (table
, "const template i386_optab[] =\n{\n");
612 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
615 p
= remove_leading_whitespaces (buf
);
618 str
= strstr (p
, "//");
622 /* Remove trailing white spaces. */
623 remove_trailing_whitespaces (p
);
628 fprintf (table
, "%s\n", p
);
636 last
= p
+ strlen (p
);
639 name
= next_field (p
, ',', &str
);
644 /* Find number of operands. */
645 operands
= next_field (str
, ',', &str
);
650 /* Find base_opcode. */
651 base_opcode
= next_field (str
, ',', &str
);
656 /* Find extension_opcode. */
657 extension_opcode
= next_field (str
, ',', &str
);
662 /* Find opcode_length. */
663 opcode_length
= next_field (str
, ',', &str
);
668 /* Find cpu_flags. */
669 cpu_flags
= next_field (str
, ',', &str
);
674 /* Find opcode_modifier. */
675 opcode_modifier
= next_field (str
, ',', &str
);
680 /* Remove the first {. */
681 str
= remove_leading_whitespaces (str
);
684 str
= remove_leading_whitespaces (str
+ 1);
688 /* There are at least "X}". */
692 /* Remove trailing white spaces and }. */
696 if (ISSPACE (str
[i
]) || str
[i
] == '}')
705 /* Find operand_types. */
706 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
710 operand_types
[i
] = NULL
;
714 operand_types
[i
] = next_field (str
, ',', &str
);
715 if (*operand_types
[i
] == '0')
718 operand_types
[i
] = NULL
;
723 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
724 name
, operands
, base_opcode
, extension_opcode
,
727 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ");
729 process_i386_opcode_modifier (table
, opcode_modifier
);
731 fprintf (table
, " { ");
733 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
735 if (operand_types
[i
] == NULL
736 || *operand_types
[i
] == '0')
739 process_i386_operand_type (table
, "0", 0, "\t ");
744 fprintf (table
, ",\n ");
746 process_i386_operand_type (table
, operand_types
[i
], 0,
749 fprintf (table
, " } },\n");
754 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
756 process_i386_cpu_flag (table
, "0", 0, ",", " ");
758 process_i386_opcode_modifier (table
, "0");
760 fprintf (table
, " { ");
761 process_i386_operand_type (table
, "0", 0, "\t ");
762 fprintf (table
, " } }\n");
764 fprintf (table
, "};\n");
768 process_i386_registers (FILE *table
)
770 FILE *fp
= fopen ("i386-reg.tbl", "r");
772 char *str
, *p
, *last
;
773 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
776 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
779 fprintf (table
, "\n/* i386 register table. */\n\n");
780 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
784 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
787 p
= remove_leading_whitespaces (buf
);
790 str
= strstr (p
, "//");
794 /* Remove trailing white spaces. */
795 remove_trailing_whitespaces (p
);
800 fprintf (table
, "%s\n", p
);
808 last
= p
+ strlen (p
);
811 reg_name
= next_field (p
, ',', &str
);
817 reg_type
= next_field (str
, ',', &str
);
822 /* Find reg_flags. */
823 reg_flags
= next_field (str
, ',', &str
);
829 reg_num
= next_field (str
, ',', &str
);
831 fprintf (table
, " { \"%s\",\n ", reg_name
);
833 process_i386_operand_type (table
, reg_type
, 0, "\t");
835 fprintf (table
, ",\n %s, %s },\n", reg_flags
, reg_num
);
840 fprintf (table
, "};\n");
842 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
846 process_i386_initializers (void)
849 FILE *fp
= fopen ("i386-init.h", "w");
853 fail (_("can't create i386-init.h, errno = %s\n"),
856 process_copyright (fp
);
858 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
860 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
861 init
= xstrdup (cpu_flag_init
[i
].init
);
862 process_i386_cpu_flag (fp
, init
, 1, "", " ");
866 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
868 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
869 init
= xstrdup (operand_type_init
[i
].init
);
870 process_i386_operand_type (fp
, init
, 1, " ");
878 /* Program options. */
879 #define OPTION_SRCDIR 200
881 struct option long_options
[] =
883 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
884 {"debug", no_argument
, NULL
, 'd'},
885 {"version", no_argument
, NULL
, 'V'},
886 {"help", no_argument
, NULL
, 'h'},
887 {0, no_argument
, NULL
, 0}
893 printf ("%s: version 1.0\n", program_name
);
898 usage (FILE * stream
, int status
)
900 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
906 main (int argc
, char **argv
)
908 extern int chdir (char *);
913 program_name
= *argv
;
914 xmalloc_set_program_name (program_name
);
916 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
941 if (chdir (srcdir
) != 0)
942 fail (_("unable to change directory to \"%s\", errno = %s\n"),
943 srcdir
, xstrerror (errno
));
945 /* Check the unused bitfield in i386_cpu_flags. */
947 c
= CpuNumOfBits
- CpuMax
- 1;
949 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
952 /* Check the unused bitfield in i386_operand_type. */
954 c
= OTNumOfBits
- OTMax
- 1;
956 fail (_("%d unused bits in i386_operand_type.\n"), c
);
959 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
962 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
963 sizeof (opcode_modifiers
[0]), compare
);
965 qsort (operand_types
, ARRAY_SIZE (operand_types
),
966 sizeof (operand_types
[0]), compare
);
968 table
= fopen ("i386-tbl.h", "w");
970 fail (_("can't create i386-tbl.h, errno = %s\n"),
973 process_copyright (table
);
975 process_i386_opcodes (table
);
976 process_i386_registers (table
);
977 process_i386_initializers ();