1 /* Copyright 2007, 2008, 2009, 2010, 2011
2 Free Software Foundation, Inc.
4 This file is part of the GNU opcodes library.
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
25 #include "libiberty.h"
27 #include "safe-ctype.h"
32 #define _(String) gettext (String)
34 static const char *program_name = NULL;
37 typedef struct initializer
43 static initializer cpu_flag_init[] =
45 { "CPU_UNKNOWN_FLAGS",
46 "~(CpuL1OM|CpuK1OM)" },
47 { "CPU_GENERIC32_FLAGS",
48 "Cpu186|Cpu286|Cpu386" },
49 { "CPU_GENERIC64_FLAGS",
50 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuLM" },
58 "Cpu186|Cpu286|Cpu386" },
60 "Cpu186|Cpu286|Cpu386|Cpu486" },
62 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu387" },
64 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687" },
65 { "CPU_PENTIUMPRO_FLAGS",
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop" },
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX" },
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE" },
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2" },
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuRdtscp|CpuLM" },
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX" },
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuNop|CpuMMX|Cpu3dnow" },
86 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA" },
88 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
89 { "CPU_AMDFAM10_FLAGS",
90 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
92 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA4|CpuXOP|CpuLWP" },
94 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA4|CpuXOP|CpuLWP|CpuBMI|CpuTBM|CpuF16C" },
102 "Cpu8087|Cpu287|Cpu387|Cpu687|CpuFISTTP" },
103 { "CPU_CLFLUSH_FLAGS",
107 { "CPU_SYSCALL_FLAGS",
114 "CpuMMX|CpuSSE|CpuSSE2" },
116 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
118 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
119 { "CPU_SSE4_1_FLAGS",
120 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
121 { "CPU_SSE4_2_FLAGS",
122 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
123 { "CPU_ANY_SSE_FLAGS",
124 "CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuAVX|CpuAVX2" },
131 { "CPU_XSAVEOPT_FLAGS",
134 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
135 { "CPU_PCLMUL_FLAGS",
136 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
138 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
140 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA4" },
142 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP" },
151 { "CPU_RDTSCP_FLAGS",
155 { "CPU_FSGSBASE_FLAGS",
169 { "CPU_INVPCID_FLAGS",
171 { "CPU_VMFUNC_FLAGS",
175 { "CPU_3DNOWA_FLAGS",
176 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
177 { "CPU_PADLOCK_FLAGS",
182 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
186 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
188 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2" },
189 { "CPU_ANY_AVX_FLAGS",
197 static initializer operand_type_init[] =
199 { "OPERAND_TYPE_NONE",
201 { "OPERAND_TYPE_REG8",
203 { "OPERAND_TYPE_REG16",
205 { "OPERAND_TYPE_REG32",
207 { "OPERAND_TYPE_REG64",
209 { "OPERAND_TYPE_IMM1",
211 { "OPERAND_TYPE_IMM8",
213 { "OPERAND_TYPE_IMM8S",
215 { "OPERAND_TYPE_IMM16",
217 { "OPERAND_TYPE_IMM32",
219 { "OPERAND_TYPE_IMM32S",
221 { "OPERAND_TYPE_IMM64",
223 { "OPERAND_TYPE_BASEINDEX",
225 { "OPERAND_TYPE_DISP8",
227 { "OPERAND_TYPE_DISP16",
229 { "OPERAND_TYPE_DISP32",
231 { "OPERAND_TYPE_DISP32S",
233 { "OPERAND_TYPE_DISP64",
235 { "OPERAND_TYPE_INOUTPORTREG",
237 { "OPERAND_TYPE_SHIFTCOUNT",
239 { "OPERAND_TYPE_CONTROL",
241 { "OPERAND_TYPE_TEST",
243 { "OPERAND_TYPE_DEBUG",
245 { "OPERAND_TYPE_FLOATREG",
247 { "OPERAND_TYPE_FLOATACC",
249 { "OPERAND_TYPE_SREG2",
251 { "OPERAND_TYPE_SREG3",
253 { "OPERAND_TYPE_ACC",
255 { "OPERAND_TYPE_JUMPABSOLUTE",
257 { "OPERAND_TYPE_REGMMX",
259 { "OPERAND_TYPE_REGXMM",
261 { "OPERAND_TYPE_REGYMM",
263 { "OPERAND_TYPE_ESSEG",
265 { "OPERAND_TYPE_ACC32",
267 { "OPERAND_TYPE_ACC64",
269 { "OPERAND_TYPE_INOUTPORTREG",
271 { "OPERAND_TYPE_REG16_INOUTPORTREG",
272 "Reg16|InOutPortReg" },
273 { "OPERAND_TYPE_DISP16_32",
275 { "OPERAND_TYPE_ANYDISP",
276 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
277 { "OPERAND_TYPE_IMM16_32",
279 { "OPERAND_TYPE_IMM16_32S",
281 { "OPERAND_TYPE_IMM16_32_32S",
282 "Imm16|Imm32|Imm32S" },
283 { "OPERAND_TYPE_IMM32_32S_DISP32",
284 "Imm32|Imm32S|Disp32" },
285 { "OPERAND_TYPE_IMM64_DISP64",
287 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
288 "Imm32|Imm32S|Imm64|Disp32" },
289 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
290 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
291 { "OPERAND_TYPE_VEC_IMM4",
295 typedef struct bitfield
302 #define BITFIELD(n) { n, 0, #n }
304 static bitfield cpu_flags[] =
312 BITFIELD (CpuClflush),
314 BITFIELD (CpuSYSCALL),
319 BITFIELD (CpuFISTTP),
325 BITFIELD (CpuSSE4_1),
326 BITFIELD (CpuSSE4_2),
333 BITFIELD (Cpu3dnowA),
334 BITFIELD (CpuPadLock),
340 BITFIELD (CpuXsaveopt),
342 BITFIELD (CpuPCLMUL),
352 BITFIELD (CpuRdtscp),
353 BITFIELD (CpuFSGSBase),
360 BITFIELD (CpuINVPCID),
361 BITFIELD (CpuVMFUNC),
365 BITFIELD (CpuUnused),
369 static bitfield opcode_modifiers[] =
375 BITFIELD (ShortForm),
377 BITFIELD (JumpDword),
379 BITFIELD (JumpInterSegment),
386 BITFIELD (CheckRegSize),
387 BITFIELD (IgnoreSize),
388 BITFIELD (DefaultSize),
397 BITFIELD (IsLockable),
398 BITFIELD (RegKludge),
399 BITFIELD (FirstXmm0),
400 BITFIELD (Implicit1stXmm0),
401 BITFIELD (HLEPrefixOk),
404 BITFIELD (AddrPrefixOp0),
413 BITFIELD (VexOpcode),
414 BITFIELD (VexSources),
415 BITFIELD (VexImmExt),
420 BITFIELD (ATTMnemonic),
421 BITFIELD (ATTSyntax),
422 BITFIELD (IntelSyntax),
425 static bitfield operand_types[] =
442 BITFIELD (BaseIndex),
448 BITFIELD (InOutPortReg),
449 BITFIELD (ShiftCount),
457 BITFIELD (JumpAbsolute),
469 BITFIELD (Unspecified),
477 static const char *filename;
480 compare (const void *x, const void *y)
482 const bitfield *xp = (const bitfield *) x;
483 const bitfield *yp = (const bitfield *) y;
484 return xp->position - yp->position;
488 fail (const char *message, ...)
492 va_start (args, message);
493 fprintf (stderr, _("%s: Error: "), program_name);
494 vfprintf (stderr, message, args);
500 process_copyright (FILE *fp)
502 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
503 /* Copyright 2007, 2008, 2009, 2010, 2011\n\
504 Free Software Foundation, Inc.\n\
506 This file is part of the GNU opcodes library.\n\
508 This library is free software; you can redistribute it and/or modify\n\
509 it under the terms of the GNU General Public License as published by\n\
510 the Free Software Foundation; either version 3, or (at your option)\n\
511 any later version.\n\
513 It is distributed in the hope that it will be useful, but WITHOUT\n\
514 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
515 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
516 License for more details.\n\
518 You should have received a copy of the GNU General Public License\n\
519 along with this program; if not, write to the Free Software\n\
520 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
521 MA 02110-1301, USA. */\n");
524 /* Remove leading white spaces. */
527 remove_leading_whitespaces (char *str)
529 while (ISSPACE (*str))
534 /* Remove trailing white spaces. */
537 remove_trailing_whitespaces (char *str)
539 size_t last = strlen (str);
547 if (ISSPACE (str [last]))
555 /* Find next field separated by SEP and terminate it. Return a
556 pointer to the one after it. */
559 next_field (char *str, char sep, char **next, char *last)
563 p = remove_leading_whitespaces (str);
564 for (str = p; *str != sep && *str != '\0'; str++);
567 remove_trailing_whitespaces (p);
578 set_bitfield (const char *f, bitfield *array, int value,
579 unsigned int size, int lineno)
583 if (strcmp (f, "CpuFP") == 0)
585 set_bitfield("Cpu387", array, value, size, lineno);
586 set_bitfield("Cpu287", array, value, size, lineno);
589 else if (strcmp (f, "Mmword") == 0)
591 else if (strcmp (f, "Oword") == 0)
594 for (i = 0; i < size; i++)
595 if (strcasecmp (array[i].name, f) == 0)
597 array[i].value = value;
603 const char *v = strchr (f, '=');
610 for (i = 0; i < size; i++)
611 if (strncasecmp (array[i].name, f, n) == 0)
613 value = strtol (v + 1, &end, 0);
616 array[i].value = value;
625 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
627 fail (_("Unknown bitfield: %s\n"), f);
631 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
632 int macro, const char *comma, const char *indent)
636 fprintf (table, "%s{ { ", indent);
638 for (i = 0; i < size - 1; i++)
640 fprintf (table, "%d, ", flags[i].value);
641 if (((i + 1) % 20) == 0)
643 /* We need \\ for macro. */
645 fprintf (table, " \\\n %s", indent);
647 fprintf (table, "\n %s", indent);
651 fprintf (table, "%d } }%s\n", flags[i].value, comma);
655 process_i386_cpu_flag (FILE *table, char *flag, int macro,
656 const char *comma, const char *indent,
659 char *str, *next, *last;
661 bitfield flags [ARRAY_SIZE (cpu_flags)];
663 /* Copy the default cpu flags. */
664 memcpy (flags, cpu_flags, sizeof (cpu_flags));
666 if (strcasecmp (flag, "unknown") == 0)
668 /* We turn on everything except for cpu64 in case of
669 CPU_UNKNOWN_FLAGS. */
670 for (i = 0; i < ARRAY_SIZE (flags); i++)
671 if (flags[i].position != Cpu64)
674 else if (flag[0] == '~')
676 last = flag + strlen (flag);
683 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
690 /* First we turn on everything except for cpu64. */
691 for (i = 0; i < ARRAY_SIZE (flags); i++)
692 if (flags[i].position != Cpu64)
695 /* Turn off selective bits. */
696 for (; next && next < last; )
698 str = next_field (next, '|', &next, last);
700 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
703 else if (strcmp (flag, "0"))
705 /* Turn on selective bits. */
706 last = flag + strlen (flag);
707 for (next = flag; next && next < last; )
709 str = next_field (next, '|', &next, last);
711 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
715 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
720 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
724 fprintf (table, " { ");
726 for (i = 0; i < size - 1; i++)
728 fprintf (table, "%d, ", modifier[i].value);
729 if (((i + 1) % 20) == 0)
730 fprintf (table, "\n ");
733 fprintf (table, "%d },\n", modifier[i].value);
737 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
739 char *str, *next, *last;
740 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
742 /* Copy the default opcode modifier. */
743 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
745 if (strcmp (mod, "0"))
747 last = mod + strlen (mod);
748 for (next = mod; next && next < last; )
750 str = next_field (next, '|', &next, last);
752 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
756 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
760 output_operand_type (FILE *table, bitfield *types, unsigned int size,
761 int macro, const char *indent)
765 fprintf (table, "{ { ");
767 for (i = 0; i < size - 1; i++)
769 fprintf (table, "%d, ", types[i].value);
770 if (((i + 1) % 20) == 0)
772 /* We need \\ for macro. */
774 fprintf (table, "\\\n%s", indent);
776 fprintf (table, "\n%s", indent);
780 fprintf (table, "%d } }", types[i].value);
784 process_i386_operand_type (FILE *table, char *op, int macro,
785 const char *indent, int lineno)
787 char *str, *next, *last;
788 bitfield types [ARRAY_SIZE (operand_types)];
790 /* Copy the default operand type. */
791 memcpy (types, operand_types, sizeof (types));
793 if (strcmp (op, "0"))
795 last = op + strlen (op);
796 for (next = op; next && next < last; )
798 str = next_field (next, '|', &next, last);
800 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
803 output_operand_type (table, types, ARRAY_SIZE (types), macro,
808 output_i386_opcode (FILE *table, const char *name, char *str,
809 char *last, int lineno)
812 char *operands, *base_opcode, *extension_opcode, *opcode_length;
813 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
815 /* Find number of operands. */
816 operands = next_field (str, ',', &str, last);
818 /* Find base_opcode. */
819 base_opcode = next_field (str, ',', &str, last);
821 /* Find extension_opcode. */
822 extension_opcode = next_field (str, ',', &str, last);
824 /* Find opcode_length. */
825 opcode_length = next_field (str, ',', &str, last);
827 /* Find cpu_flags. */
828 cpu_flags = next_field (str, ',', &str, last);
830 /* Find opcode_modifier. */
831 opcode_modifier = next_field (str, ',', &str, last);
833 /* Remove the first {. */
834 str = remove_leading_whitespaces (str);
837 str = remove_leading_whitespaces (str + 1);
841 /* There are at least "X}". */
845 /* Remove trailing white spaces and }. */
849 if (ISSPACE (str[i]) || str[i] == '}')
858 /* Find operand_types. */
859 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
863 operand_types [i] = NULL;
867 operand_types [i] = next_field (str, ',', &str, last);
868 if (*operand_types[i] == '0')
871 operand_types[i] = NULL;
876 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
877 name, operands, base_opcode, extension_opcode,
880 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
882 process_i386_opcode_modifier (table, opcode_modifier, lineno);
884 fprintf (table, " { ");
886 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
888 if (operand_types[i] == NULL || *operand_types[i] == '0')
891 process_i386_operand_type (table, "0", 0, "\t ", lineno);
896 fprintf (table, ",\n ");
898 process_i386_operand_type (table, operand_types[i], 0,
901 fprintf (table, " } },\n");
904 struct opcode_hash_entry
906 struct opcode_hash_entry *next;
912 /* Calculate the hash value of an opcode hash entry P. */
915 opcode_hash_hash (const void *p)
917 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
918 return htab_hash_string (entry->name);
921 /* Compare a string Q against an opcode hash entry P. */
924 opcode_hash_eq (const void *p, const void *q)
926 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
927 const char *name = (const char *) q;
928 return strcmp (name, entry->name) == 0;
932 process_i386_opcodes (FILE *table)
937 char *str, *p, *last, *name;
938 struct opcode_hash_entry **hash_slot, **entry, *next;
939 htab_t opcode_hash_table;
940 struct opcode_hash_entry **opcode_array;
941 unsigned int opcode_array_size = 1024;
944 filename = "i386-opc.tbl";
945 fp = fopen (filename, "r");
948 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
952 opcode_array = (struct opcode_hash_entry **)
953 xmalloc (sizeof (*opcode_array) * opcode_array_size);
955 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
956 opcode_hash_eq, NULL,
959 fprintf (table, "\n/* i386 opcode table. */\n\n");
960 fprintf (table, "const insn_template i386_optab[] =\n{\n");
962 /* Put everything on opcode array. */
965 if (fgets (buf, sizeof (buf), fp) == NULL)
970 p = remove_leading_whitespaces (buf);
973 str = strstr (p, "//");
977 /* Remove trailing white spaces. */
978 remove_trailing_whitespaces (p);
983 /* Ignore comments. */
991 last = p + strlen (p);
994 name = next_field (p, ',', &str, last);
996 /* Get the slot in hash table. */
997 hash_slot = (struct opcode_hash_entry **)
998 htab_find_slot_with_hash (opcode_hash_table, name,
999 htab_hash_string (name),
1002 if (*hash_slot == NULL)
1004 /* It is the new one. Put it on opcode array. */
1005 if (i >= opcode_array_size)
1007 /* Grow the opcode array when needed. */
1008 opcode_array_size += 1024;
1009 opcode_array = (struct opcode_hash_entry **)
1010 xrealloc (opcode_array,
1011 sizeof (*opcode_array) * opcode_array_size);
1014 opcode_array[i] = (struct opcode_hash_entry *)
1015 xmalloc (sizeof (struct opcode_hash_entry));
1016 opcode_array[i]->next = NULL;
1017 opcode_array[i]->name = xstrdup (name);
1018 opcode_array[i]->opcode = xstrdup (str);
1019 opcode_array[i]->lineno = lineno;
1020 *hash_slot = opcode_array[i];
1025 /* Append it to the existing one. */
1027 while ((*entry) != NULL)
1028 entry = &(*entry)->next;
1029 *entry = (struct opcode_hash_entry *)
1030 xmalloc (sizeof (struct opcode_hash_entry));
1031 (*entry)->next = NULL;
1032 (*entry)->name = (*hash_slot)->name;
1033 (*entry)->opcode = xstrdup (str);
1034 (*entry)->lineno = lineno;
1038 /* Process opcode array. */
1039 for (j = 0; j < i; j++)
1041 for (next = opcode_array[j]; next; next = next->next)
1045 lineno = next->lineno;
1046 last = str + strlen (str);
1047 output_i386_opcode (table, name, str, last, lineno);
1053 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1055 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1057 process_i386_opcode_modifier (table, "0", -1);
1059 fprintf (table, " { ");
1060 process_i386_operand_type (table, "0", 0, "\t ", -1);
1061 fprintf (table, " } }\n");
1063 fprintf (table, "};\n");
1067 process_i386_registers (FILE *table)
1071 char *str, *p, *last;
1072 char *reg_name, *reg_type, *reg_flags, *reg_num;
1073 char *dw2_32_num, *dw2_64_num;
1076 filename = "i386-reg.tbl";
1077 fp = fopen (filename, "r");
1079 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1082 fprintf (table, "\n/* i386 register table. */\n\n");
1083 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1087 if (fgets (buf, sizeof (buf), fp) == NULL)
1092 p = remove_leading_whitespaces (buf);
1094 /* Skip comments. */
1095 str = strstr (p, "//");
1099 /* Remove trailing white spaces. */
1100 remove_trailing_whitespaces (p);
1105 fprintf (table, "%s\n", p);
1113 last = p + strlen (p);
1115 /* Find reg_name. */
1116 reg_name = next_field (p, ',', &str, last);
1118 /* Find reg_type. */
1119 reg_type = next_field (str, ',', &str, last);
1121 /* Find reg_flags. */
1122 reg_flags = next_field (str, ',', &str, last);
1125 reg_num = next_field (str, ',', &str, last);
1127 fprintf (table, " { \"%s\",\n ", reg_name);
1129 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1131 /* Find 32-bit Dwarf2 register number. */
1132 dw2_32_num = next_field (str, ',', &str, last);
1134 /* Find 64-bit Dwarf2 register number. */
1135 dw2_64_num = next_field (str, ',', &str, last);
1137 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1138 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1143 fprintf (table, "};\n");
1145 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1149 process_i386_initializers (void)
1152 FILE *fp = fopen ("i386-init.h", "w");
1156 fail (_("can't create i386-init.h, errno = %s\n"),
1159 process_copyright (fp);
1161 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1163 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1164 init = xstrdup (cpu_flag_init[i].init);
1165 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1169 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1171 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1172 init = xstrdup (operand_type_init[i].init);
1173 process_i386_operand_type (fp, init, 1, " ", -1);
1181 /* Program options. */
1182 #define OPTION_SRCDIR 200
1184 struct option long_options[] =
1186 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1187 {"debug", no_argument, NULL, 'd'},
1188 {"version", no_argument, NULL, 'V'},
1189 {"help", no_argument, NULL, 'h'},
1190 {0, no_argument, NULL, 0}
1194 print_version (void)
1196 printf ("%s: version 1.0\n", program_name);
1201 usage (FILE * stream, int status)
1203 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1209 main (int argc, char **argv)
1211 extern int chdir (char *);
1212 char *srcdir = NULL;
1216 program_name = *argv;
1217 xmalloc_set_program_name (program_name);
1219 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1244 if (chdir (srcdir) != 0)
1245 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1246 srcdir, xstrerror (errno));
1248 /* Check the unused bitfield in i386_cpu_flags. */
1250 c = CpuNumOfBits - CpuMax - 1;
1252 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1255 /* Check the unused bitfield in i386_operand_type. */
1257 c = OTNumOfBits - OTMax - 1;
1259 fail (_("%d unused bits in i386_operand_type.\n"), c);
1262 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1265 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1266 sizeof (opcode_modifiers [0]), compare);
1268 qsort (operand_types, ARRAY_SIZE (operand_types),
1269 sizeof (operand_types [0]), compare);
1271 table = fopen ("i386-tbl.h", "w");
1273 fail (_("can't create i386-tbl.h, errno = %s\n"),
1276 process_copyright (table);
1278 process_i386_opcodes (table);
1279 process_i386_registers (table);
1280 process_i386_initializers ();