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",
165 { "CPU_INVPCID_FLAGS",
167 { "CPU_VMFUNC_FLAGS",
171 { "CPU_3DNOWA_FLAGS",
172 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
173 { "CPU_PADLOCK_FLAGS",
178 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
182 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
184 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2" },
185 { "CPU_ANY_AVX_FLAGS",
193 static initializer operand_type_init[] =
195 { "OPERAND_TYPE_NONE",
197 { "OPERAND_TYPE_REG8",
199 { "OPERAND_TYPE_REG16",
201 { "OPERAND_TYPE_REG32",
203 { "OPERAND_TYPE_REG64",
205 { "OPERAND_TYPE_IMM1",
207 { "OPERAND_TYPE_IMM8",
209 { "OPERAND_TYPE_IMM8S",
211 { "OPERAND_TYPE_IMM16",
213 { "OPERAND_TYPE_IMM32",
215 { "OPERAND_TYPE_IMM32S",
217 { "OPERAND_TYPE_IMM64",
219 { "OPERAND_TYPE_BASEINDEX",
221 { "OPERAND_TYPE_DISP8",
223 { "OPERAND_TYPE_DISP16",
225 { "OPERAND_TYPE_DISP32",
227 { "OPERAND_TYPE_DISP32S",
229 { "OPERAND_TYPE_DISP64",
231 { "OPERAND_TYPE_INOUTPORTREG",
233 { "OPERAND_TYPE_SHIFTCOUNT",
235 { "OPERAND_TYPE_CONTROL",
237 { "OPERAND_TYPE_TEST",
239 { "OPERAND_TYPE_DEBUG",
241 { "OPERAND_TYPE_FLOATREG",
243 { "OPERAND_TYPE_FLOATACC",
245 { "OPERAND_TYPE_SREG2",
247 { "OPERAND_TYPE_SREG3",
249 { "OPERAND_TYPE_ACC",
251 { "OPERAND_TYPE_JUMPABSOLUTE",
253 { "OPERAND_TYPE_REGMMX",
255 { "OPERAND_TYPE_REGXMM",
257 { "OPERAND_TYPE_REGYMM",
259 { "OPERAND_TYPE_ESSEG",
261 { "OPERAND_TYPE_ACC32",
263 { "OPERAND_TYPE_ACC64",
265 { "OPERAND_TYPE_INOUTPORTREG",
267 { "OPERAND_TYPE_REG16_INOUTPORTREG",
268 "Reg16|InOutPortReg" },
269 { "OPERAND_TYPE_DISP16_32",
271 { "OPERAND_TYPE_ANYDISP",
272 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
273 { "OPERAND_TYPE_IMM16_32",
275 { "OPERAND_TYPE_IMM16_32S",
277 { "OPERAND_TYPE_IMM16_32_32S",
278 "Imm16|Imm32|Imm32S" },
279 { "OPERAND_TYPE_IMM32_32S_DISP32",
280 "Imm32|Imm32S|Disp32" },
281 { "OPERAND_TYPE_IMM64_DISP64",
283 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
284 "Imm32|Imm32S|Imm64|Disp32" },
285 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
286 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
287 { "OPERAND_TYPE_VEC_IMM4",
291 typedef struct bitfield
298 #define BITFIELD(n) { n, 0, #n }
300 static bitfield cpu_flags[] =
308 BITFIELD (CpuClflush),
310 BITFIELD (CpuSYSCALL),
315 BITFIELD (CpuFISTTP),
321 BITFIELD (CpuSSE4_1),
322 BITFIELD (CpuSSE4_2),
329 BITFIELD (Cpu3dnowA),
330 BITFIELD (CpuPadLock),
336 BITFIELD (CpuXsaveopt),
338 BITFIELD (CpuPCLMUL),
348 BITFIELD (CpuRdtscp),
349 BITFIELD (CpuFSGSBase),
354 BITFIELD (CpuINVPCID),
355 BITFIELD (CpuVMFUNC),
359 BITFIELD (CpuUnused),
363 static bitfield opcode_modifiers[] =
369 BITFIELD (ShortForm),
371 BITFIELD (JumpDword),
373 BITFIELD (JumpInterSegment),
380 BITFIELD (CheckRegSize),
381 BITFIELD (IgnoreSize),
382 BITFIELD (DefaultSize),
391 BITFIELD (IsLockable),
392 BITFIELD (RegKludge),
393 BITFIELD (FirstXmm0),
394 BITFIELD (Implicit1stXmm0),
397 BITFIELD (AddrPrefixOp0),
406 BITFIELD (VexOpcode),
407 BITFIELD (VexSources),
408 BITFIELD (VexImmExt),
413 BITFIELD (ATTMnemonic),
414 BITFIELD (ATTSyntax),
415 BITFIELD (IntelSyntax),
418 static bitfield operand_types[] =
435 BITFIELD (BaseIndex),
441 BITFIELD (InOutPortReg),
442 BITFIELD (ShiftCount),
450 BITFIELD (JumpAbsolute),
462 BITFIELD (Unspecified),
470 static const char *filename;
473 compare (const void *x, const void *y)
475 const bitfield *xp = (const bitfield *) x;
476 const bitfield *yp = (const bitfield *) y;
477 return xp->position - yp->position;
481 fail (const char *message, ...)
485 va_start (args, message);
486 fprintf (stderr, _("%s: Error: "), program_name);
487 vfprintf (stderr, message, args);
493 process_copyright (FILE *fp)
495 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
496 /* Copyright 2007, 2008, 2009, 2010, 2011\n\
497 Free Software Foundation, Inc.\n\
499 This file is part of the GNU opcodes library.\n\
501 This library is free software; you can redistribute it and/or modify\n\
502 it under the terms of the GNU General Public License as published by\n\
503 the Free Software Foundation; either version 3, or (at your option)\n\
504 any later version.\n\
506 It is distributed in the hope that it will be useful, but WITHOUT\n\
507 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
508 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
509 License for more details.\n\
511 You should have received a copy of the GNU General Public License\n\
512 along with this program; if not, write to the Free Software\n\
513 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
514 MA 02110-1301, USA. */\n");
517 /* Remove leading white spaces. */
520 remove_leading_whitespaces (char *str)
522 while (ISSPACE (*str))
527 /* Remove trailing white spaces. */
530 remove_trailing_whitespaces (char *str)
532 size_t last = strlen (str);
540 if (ISSPACE (str [last]))
548 /* Find next field separated by SEP and terminate it. Return a
549 pointer to the one after it. */
552 next_field (char *str, char sep, char **next, char *last)
556 p = remove_leading_whitespaces (str);
557 for (str = p; *str != sep && *str != '\0'; str++);
560 remove_trailing_whitespaces (p);
571 set_bitfield (const char *f, bitfield *array, int value,
572 unsigned int size, int lineno)
576 if (strcmp (f, "CpuFP") == 0)
578 set_bitfield("Cpu387", array, value, size, lineno);
579 set_bitfield("Cpu287", array, value, size, lineno);
582 else if (strcmp (f, "Mmword") == 0)
584 else if (strcmp (f, "Oword") == 0)
587 for (i = 0; i < size; i++)
588 if (strcasecmp (array[i].name, f) == 0)
590 array[i].value = value;
596 const char *v = strchr (f, '=');
603 for (i = 0; i < size; i++)
604 if (strncasecmp (array[i].name, f, n) == 0)
606 value = strtol (v + 1, &end, 0);
609 array[i].value = value;
618 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
620 fail (_("Unknown bitfield: %s\n"), f);
624 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
625 int macro, const char *comma, const char *indent)
629 fprintf (table, "%s{ { ", indent);
631 for (i = 0; i < size - 1; i++)
633 fprintf (table, "%d, ", flags[i].value);
634 if (((i + 1) % 20) == 0)
636 /* We need \\ for macro. */
638 fprintf (table, " \\\n %s", indent);
640 fprintf (table, "\n %s", indent);
644 fprintf (table, "%d } }%s\n", flags[i].value, comma);
648 process_i386_cpu_flag (FILE *table, char *flag, int macro,
649 const char *comma, const char *indent,
652 char *str, *next, *last;
654 bitfield flags [ARRAY_SIZE (cpu_flags)];
656 /* Copy the default cpu flags. */
657 memcpy (flags, cpu_flags, sizeof (cpu_flags));
659 if (strcasecmp (flag, "unknown") == 0)
661 /* We turn on everything except for cpu64 in case of
662 CPU_UNKNOWN_FLAGS. */
663 for (i = 0; i < ARRAY_SIZE (flags); i++)
664 if (flags[i].position != Cpu64)
667 else if (flag[0] == '~')
669 last = flag + strlen (flag);
676 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
683 /* First we turn on everything except for cpu64. */
684 for (i = 0; i < ARRAY_SIZE (flags); i++)
685 if (flags[i].position != Cpu64)
688 /* Turn off selective bits. */
689 for (; next && next < last; )
691 str = next_field (next, '|', &next, last);
693 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
696 else if (strcmp (flag, "0"))
698 /* Turn on selective bits. */
699 last = flag + strlen (flag);
700 for (next = flag; next && next < last; )
702 str = next_field (next, '|', &next, last);
704 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
708 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
713 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
717 fprintf (table, " { ");
719 for (i = 0; i < size - 1; i++)
721 fprintf (table, "%d, ", modifier[i].value);
722 if (((i + 1) % 20) == 0)
723 fprintf (table, "\n ");
726 fprintf (table, "%d },\n", modifier[i].value);
730 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
732 char *str, *next, *last;
733 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
735 /* Copy the default opcode modifier. */
736 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
738 if (strcmp (mod, "0"))
740 last = mod + strlen (mod);
741 for (next = mod; next && next < last; )
743 str = next_field (next, '|', &next, last);
745 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
749 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
753 output_operand_type (FILE *table, bitfield *types, unsigned int size,
754 int macro, const char *indent)
758 fprintf (table, "{ { ");
760 for (i = 0; i < size - 1; i++)
762 fprintf (table, "%d, ", types[i].value);
763 if (((i + 1) % 20) == 0)
765 /* We need \\ for macro. */
767 fprintf (table, "\\\n%s", indent);
769 fprintf (table, "\n%s", indent);
773 fprintf (table, "%d } }", types[i].value);
777 process_i386_operand_type (FILE *table, char *op, int macro,
778 const char *indent, int lineno)
780 char *str, *next, *last;
781 bitfield types [ARRAY_SIZE (operand_types)];
783 /* Copy the default operand type. */
784 memcpy (types, operand_types, sizeof (types));
786 if (strcmp (op, "0"))
788 last = op + strlen (op);
789 for (next = op; next && next < last; )
791 str = next_field (next, '|', &next, last);
793 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
796 output_operand_type (table, types, ARRAY_SIZE (types), macro,
801 output_i386_opcode (FILE *table, const char *name, char *str,
802 char *last, int lineno)
805 char *operands, *base_opcode, *extension_opcode, *opcode_length;
806 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
808 /* Find number of operands. */
809 operands = next_field (str, ',', &str, last);
811 /* Find base_opcode. */
812 base_opcode = next_field (str, ',', &str, last);
814 /* Find extension_opcode. */
815 extension_opcode = next_field (str, ',', &str, last);
817 /* Find opcode_length. */
818 opcode_length = next_field (str, ',', &str, last);
820 /* Find cpu_flags. */
821 cpu_flags = next_field (str, ',', &str, last);
823 /* Find opcode_modifier. */
824 opcode_modifier = next_field (str, ',', &str, last);
826 /* Remove the first {. */
827 str = remove_leading_whitespaces (str);
830 str = remove_leading_whitespaces (str + 1);
834 /* There are at least "X}". */
838 /* Remove trailing white spaces and }. */
842 if (ISSPACE (str[i]) || str[i] == '}')
851 /* Find operand_types. */
852 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
856 operand_types [i] = NULL;
860 operand_types [i] = next_field (str, ',', &str, last);
861 if (*operand_types[i] == '0')
864 operand_types[i] = NULL;
869 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
870 name, operands, base_opcode, extension_opcode,
873 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
875 process_i386_opcode_modifier (table, opcode_modifier, lineno);
877 fprintf (table, " { ");
879 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
881 if (operand_types[i] == NULL || *operand_types[i] == '0')
884 process_i386_operand_type (table, "0", 0, "\t ", lineno);
889 fprintf (table, ",\n ");
891 process_i386_operand_type (table, operand_types[i], 0,
894 fprintf (table, " } },\n");
897 struct opcode_hash_entry
899 struct opcode_hash_entry *next;
905 /* Calculate the hash value of an opcode hash entry P. */
908 opcode_hash_hash (const void *p)
910 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
911 return htab_hash_string (entry->name);
914 /* Compare a string Q against an opcode hash entry P. */
917 opcode_hash_eq (const void *p, const void *q)
919 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
920 const char *name = (const char *) q;
921 return strcmp (name, entry->name) == 0;
925 process_i386_opcodes (FILE *table)
930 char *str, *p, *last, *name;
931 struct opcode_hash_entry **hash_slot, **entry, *next;
932 htab_t opcode_hash_table;
933 struct opcode_hash_entry **opcode_array;
934 unsigned int opcode_array_size = 1024;
937 filename = "i386-opc.tbl";
938 fp = fopen (filename, "r");
941 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
945 opcode_array = (struct opcode_hash_entry **)
946 xmalloc (sizeof (*opcode_array) * opcode_array_size);
948 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
949 opcode_hash_eq, NULL,
952 fprintf (table, "\n/* i386 opcode table. */\n\n");
953 fprintf (table, "const insn_template i386_optab[] =\n{\n");
955 /* Put everything on opcode array. */
958 if (fgets (buf, sizeof (buf), fp) == NULL)
963 p = remove_leading_whitespaces (buf);
966 str = strstr (p, "//");
970 /* Remove trailing white spaces. */
971 remove_trailing_whitespaces (p);
976 /* Ignore comments. */
984 last = p + strlen (p);
987 name = next_field (p, ',', &str, last);
989 /* Get the slot in hash table. */
990 hash_slot = (struct opcode_hash_entry **)
991 htab_find_slot_with_hash (opcode_hash_table, name,
992 htab_hash_string (name),
995 if (*hash_slot == NULL)
997 /* It is the new one. Put it on opcode array. */
998 if (i >= opcode_array_size)
1000 /* Grow the opcode array when needed. */
1001 opcode_array_size += 1024;
1002 opcode_array = (struct opcode_hash_entry **)
1003 xrealloc (opcode_array,
1004 sizeof (*opcode_array) * opcode_array_size);
1007 opcode_array[i] = (struct opcode_hash_entry *)
1008 xmalloc (sizeof (struct opcode_hash_entry));
1009 opcode_array[i]->next = NULL;
1010 opcode_array[i]->name = xstrdup (name);
1011 opcode_array[i]->opcode = xstrdup (str);
1012 opcode_array[i]->lineno = lineno;
1013 *hash_slot = opcode_array[i];
1018 /* Append it to the existing one. */
1020 while ((*entry) != NULL)
1021 entry = &(*entry)->next;
1022 *entry = (struct opcode_hash_entry *)
1023 xmalloc (sizeof (struct opcode_hash_entry));
1024 (*entry)->next = NULL;
1025 (*entry)->name = (*hash_slot)->name;
1026 (*entry)->opcode = xstrdup (str);
1027 (*entry)->lineno = lineno;
1031 /* Process opcode array. */
1032 for (j = 0; j < i; j++)
1034 for (next = opcode_array[j]; next; next = next->next)
1038 lineno = next->lineno;
1039 last = str + strlen (str);
1040 output_i386_opcode (table, name, str, last, lineno);
1046 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1048 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1050 process_i386_opcode_modifier (table, "0", -1);
1052 fprintf (table, " { ");
1053 process_i386_operand_type (table, "0", 0, "\t ", -1);
1054 fprintf (table, " } }\n");
1056 fprintf (table, "};\n");
1060 process_i386_registers (FILE *table)
1064 char *str, *p, *last;
1065 char *reg_name, *reg_type, *reg_flags, *reg_num;
1066 char *dw2_32_num, *dw2_64_num;
1069 filename = "i386-reg.tbl";
1070 fp = fopen (filename, "r");
1072 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1075 fprintf (table, "\n/* i386 register table. */\n\n");
1076 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1080 if (fgets (buf, sizeof (buf), fp) == NULL)
1085 p = remove_leading_whitespaces (buf);
1087 /* Skip comments. */
1088 str = strstr (p, "//");
1092 /* Remove trailing white spaces. */
1093 remove_trailing_whitespaces (p);
1098 fprintf (table, "%s\n", p);
1106 last = p + strlen (p);
1108 /* Find reg_name. */
1109 reg_name = next_field (p, ',', &str, last);
1111 /* Find reg_type. */
1112 reg_type = next_field (str, ',', &str, last);
1114 /* Find reg_flags. */
1115 reg_flags = next_field (str, ',', &str, last);
1118 reg_num = next_field (str, ',', &str, last);
1120 fprintf (table, " { \"%s\",\n ", reg_name);
1122 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1124 /* Find 32-bit Dwarf2 register number. */
1125 dw2_32_num = next_field (str, ',', &str, last);
1127 /* Find 64-bit Dwarf2 register number. */
1128 dw2_64_num = next_field (str, ',', &str, last);
1130 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1131 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1136 fprintf (table, "};\n");
1138 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1142 process_i386_initializers (void)
1145 FILE *fp = fopen ("i386-init.h", "w");
1149 fail (_("can't create i386-init.h, errno = %s\n"),
1152 process_copyright (fp);
1154 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1156 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1157 init = xstrdup (cpu_flag_init[i].init);
1158 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1162 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1164 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1165 init = xstrdup (operand_type_init[i].init);
1166 process_i386_operand_type (fp, init, 1, " ", -1);
1174 /* Program options. */
1175 #define OPTION_SRCDIR 200
1177 struct option long_options[] =
1179 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1180 {"debug", no_argument, NULL, 'd'},
1181 {"version", no_argument, NULL, 'V'},
1182 {"help", no_argument, NULL, 'h'},
1183 {0, no_argument, NULL, 0}
1187 print_version (void)
1189 printf ("%s: version 1.0\n", program_name);
1194 usage (FILE * stream, int status)
1196 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1202 main (int argc, char **argv)
1204 extern int chdir (char *);
1205 char *srcdir = NULL;
1209 program_name = *argv;
1210 xmalloc_set_program_name (program_name);
1212 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1237 if (chdir (srcdir) != 0)
1238 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1239 srcdir, xstrerror (errno));
1241 /* Check the unused bitfield in i386_cpu_flags. */
1243 c = CpuNumOfBits - CpuMax - 1;
1245 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1248 /* Check the unused bitfield in i386_operand_type. */
1250 c = OTNumOfBits - OTMax - 1;
1252 fail (_("%d unused bits in i386_operand_type.\n"), c);
1255 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1258 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1259 sizeof (opcode_modifiers [0]), compare);
1261 qsort (operand_types, ARRAY_SIZE (operand_types),
1262 sizeof (operand_types [0]), compare);
1264 table = fopen ("i386-tbl.h", "w");
1266 fail (_("can't create i386-tbl.h, errno = %s\n"),
1269 process_copyright (table);
1271 process_i386_opcodes (table);
1272 process_i386_registers (table);
1273 process_i386_initializers ();