1 /* Copyright (C) 2007-2016 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"
26 #include "safe-ctype.h"
31 #define _(String) gettext (String)
33 static const char *program_name = NULL;
36 typedef struct initializer
42 static initializer cpu_flag_init[] =
44 { "CPU_UNKNOWN_FLAGS",
45 "~(CpuL1OM|CpuK1OM)" },
46 { "CPU_GENERIC32_FLAGS",
47 "Cpu186|Cpu286|Cpu386" },
48 { "CPU_GENERIC64_FLAGS",
49 "CPU_PENTIUMPRO_FLAGS|CpuClflush|CpuSYSCALL|CPU_MMX_FLAGS|CPU_SSE2_FLAGS|CpuLM" },
55 "CPU_I186_FLAGS|Cpu286" },
57 "CPU_I286_FLAGS|Cpu386" },
59 "CPU_I386_FLAGS|Cpu486" },
61 "CPU_I486_FLAGS|CPU_387_FLAGS|Cpu586" },
63 "CPU_I586_FLAGS|Cpu686|Cpu687" },
64 { "CPU_PENTIUMPRO_FLAGS",
65 "CPU_I686_FLAGS|CpuNop" },
67 "CPU_PENTIUMPRO_FLAGS|CPU_MMX_FLAGS" },
69 "CPU_P2_FLAGS|CPU_SSE_FLAGS" },
71 "CPU_P3_FLAGS|CpuClflush|CPU_SSE2_FLAGS" },
73 "CPU_GENERIC64_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
75 "CPU_P4_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
77 "CPU_NOCONA_FLAGS|CPU_SSSE3_FLAGS" },
79 "CPU_CORE2_FLAGS|CPU_SSE4_2_FLAGS|CpuRdtscp" },
81 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CPU_MMX_FLAGS" },
83 "CPU_K6_FLAGS|Cpu3dnow" },
85 "CPU_K6_2_FLAGS|Cpu686|Cpu687|CpuNop|Cpu3dnowA" },
87 "CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
88 { "CPU_AMDFAM10_FLAGS",
89 "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuABM" },
91 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_SSE4_2_FLAGS|CpuSSE4A|CpuABM|CpuFMA4|CpuXOP|CpuLWP|CpuSVME|CpuXsave|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW" },
93 "CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
95 "CPU_BDVER2_FLAGS|CpuXsaveopt|CpuFSGSBase" },
97 "CPU_BDVER3_FLAGS|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuMWAITX" },
99 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_SSE4_2_FLAGS|CpuSSE4A|CpuABM|CpuSVME|CpuXsave|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW|CpuFMA|CpuBMI|CpuF16C|CpuXsaveopt|CpuFSGSBase|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuADX|CpuRdSeed|CpuSMAP|CpuSHA|CpuXSAVEC|CpuXSAVES|CpuClflushOpt|CpuCLZERO|CpuMWAITX" },
100 { "CPU_BTVER1_FLAGS",
101 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuABM|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME|CpuLZCNT" },
102 { "CPU_BTVER2_FLAGS",
103 "CPU_BTVER1_FLAGS|CPU_SSE4_2_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuAVX|CpuMovbe|CpuXsave|CpuXsaveopt|CpuPRFCHW" },
107 "CPU_8087_FLAGS|Cpu287" },
109 "CPU_287_FLAGS|Cpu387" },
111 "CPU_387_FLAGS|Cpu687" },
112 { "CPU_CLFLUSH_FLAGS",
116 { "CPU_SYSCALL_FLAGS",
119 "CpuRegMMX|CpuMMX" },
121 "CpuRegXMM|CpuSSE" },
123 "CPU_SSE_FLAGS|CpuSSE2" },
125 "CPU_SSE2_FLAGS|CpuSSE3" },
127 "CPU_SSE3_FLAGS|CpuSSSE3" },
128 { "CPU_SSE4_1_FLAGS",
129 "CPU_SSSE3_FLAGS|CpuSSE4_1" },
130 { "CPU_SSE4_2_FLAGS",
131 "CPU_SSE4_1_FLAGS|CpuSSE4_2" },
138 { "CPU_XSAVEOPT_FLAGS",
139 "CPU_XSAVE_FLAGS|CpuXsaveopt" },
141 "CPU_SSE2_FLAGS|CpuAES" },
142 { "CPU_PCLMUL_FLAGS",
143 "CPU_SSE2_FLAGS|CpuPCLMUL" },
145 "CPU_AVX_FLAGS|CpuFMA" },
147 "CPU_AVX_FLAGS|CpuFMA4" },
149 "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
160 { "CPU_RDTSCP_FLAGS",
164 { "CPU_FSGSBASE_FLAGS",
169 "CPU_AVX_FLAGS|CpuF16C" },
178 { "CPU_INVPCID_FLAGS",
180 { "CPU_VMFUNC_FLAGS",
183 "CPU_MMX_FLAGS|Cpu3dnow" },
184 { "CPU_3DNOWA_FLAGS",
185 "CPU_3DNOW_FLAGS|Cpu3dnowA" },
186 { "CPU_PADLOCK_FLAGS",
191 "CPU_SSE3_FLAGS|CpuSSE4a" },
195 "CPU_SSE4_2_FLAGS|CpuRegYMM|CpuAVX" },
197 "CPU_AVX_FLAGS|CpuAVX2" },
198 /* Don't use CPU_AVX2_FLAGS on CPU_AVX512F_FLAGS since AVX512F doesn't
199 support YMM registers. */
200 { "CPU_AVX512F_FLAGS",
201 "CpuVREX|CPU_SSE4_2_FLAGS|CpuRegZMM|CpuRegMask|CpuAVX|CpuAVX2|CpuAVX512F" },
202 { "CPU_AVX512CD_FLAGS",
203 "CPU_AVX512F_FLAGS|CpuAVX512CD" },
204 { "CPU_AVX512ER_FLAGS",
205 "CPU_AVX512F_FLAGS|CpuAVX512ER" },
206 { "CPU_AVX512PF_FLAGS",
207 "CPU_AVX512F_FLAGS|CpuAVX512PF" },
208 { "CPU_AVX512DQ_FLAGS",
209 "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
210 { "CPU_AVX512BW_FLAGS",
211 "CPU_AVX512F_FLAGS|CpuAVX512BW" },
212 { "CPU_AVX512VL_FLAGS",
213 /* Use CPU_AVX2_FLAGS on CPU_AVX512VL_FLAGS since AVX512VL supports YMM
215 "CPU_AVX512F_FLAGS|CPU_AVX2_FLAGS|CpuAVX512VL" },
216 { "CPU_AVX512IFMA_FLAGS",
217 "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
218 { "CPU_AVX512VBMI_FLAGS",
219 "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
225 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
226 { "CPU_IAMCU_COMPAT_FLAGS",
227 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuNo64|CpuNop" },
230 { "CPU_RDSEED_FLAGS",
232 { "CPU_PRFCHW_FLAGS",
239 "CPU_SSE2_FLAGS|CpuSHA" },
240 { "CPU_CLFLUSHOPT_FLAGS",
242 { "CPU_XSAVES_FLAGS",
243 "CPU_XSAVE_FLAGS|CpuXSAVES" },
244 { "CPU_XSAVEC_FLAGS",
245 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
246 { "CPU_PREFETCHWT1_FLAGS",
252 { "CPU_PCOMMIT_FLAGS",
254 { "CPU_CLZERO_FLAGS",
256 { "CPU_MWAITX_FLAGS",
262 { "CPU_ANY_X87_FLAGS",
263 "CPU_ANY_287_FLAGS|Cpu8087" },
264 { "CPU_ANY_287_FLAGS",
265 "CPU_ANY_387_FLAGS|Cpu287" },
266 { "CPU_ANY_387_FLAGS",
267 "CPU_ANY_687_FLAGS|Cpu387" },
268 { "CPU_ANY_687_FLAGS",
269 "Cpu687|CpuFISTTP" },
270 { "CPU_ANY_MMX_FLAGS",
271 "CPU_3DNOWA_FLAGS" },
272 { "CPU_ANY_SSE_FLAGS",
273 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
274 { "CPU_ANY_SSE2_FLAGS",
275 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
276 { "CPU_ANY_SSE3_FLAGS",
277 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
278 { "CPU_ANY_SSSE3_FLAGS",
279 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
280 { "CPU_ANY_SSE4_1_FLAGS",
281 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
282 { "CPU_ANY_SSE4_2_FLAGS",
284 { "CPU_ANY_AVX_FLAGS",
285 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
286 { "CPU_ANY_AVX2_FLAGS",
288 { "CPU_ANY_AVX512F_FLAGS",
289 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512F" },
290 { "CPU_ANY_AVX512CD_FLAGS",
292 { "CPU_ANY_AVX512ER_FLAGS",
294 { "CPU_ANY_AVX512PF_FLAGS",
296 { "CPU_ANY_AVX512DQ_FLAGS",
298 { "CPU_ANY_AVX512BW_FLAGS",
300 { "CPU_ANY_AVX512VL_FLAGS",
302 { "CPU_ANY_AVX512IFMA_FLAGS",
304 { "CPU_ANY_AVX512VBMI_FLAGS",
308 static initializer operand_type_init[] =
310 { "OPERAND_TYPE_NONE",
312 { "OPERAND_TYPE_REG8",
314 { "OPERAND_TYPE_REG16",
316 { "OPERAND_TYPE_REG32",
318 { "OPERAND_TYPE_REG64",
320 { "OPERAND_TYPE_IMM1",
322 { "OPERAND_TYPE_IMM8",
324 { "OPERAND_TYPE_IMM8S",
326 { "OPERAND_TYPE_IMM16",
328 { "OPERAND_TYPE_IMM32",
330 { "OPERAND_TYPE_IMM32S",
332 { "OPERAND_TYPE_IMM64",
334 { "OPERAND_TYPE_BASEINDEX",
336 { "OPERAND_TYPE_DISP8",
338 { "OPERAND_TYPE_DISP16",
340 { "OPERAND_TYPE_DISP32",
342 { "OPERAND_TYPE_DISP32S",
344 { "OPERAND_TYPE_DISP64",
346 { "OPERAND_TYPE_INOUTPORTREG",
348 { "OPERAND_TYPE_SHIFTCOUNT",
350 { "OPERAND_TYPE_CONTROL",
352 { "OPERAND_TYPE_TEST",
354 { "OPERAND_TYPE_DEBUG",
356 { "OPERAND_TYPE_FLOATREG",
358 { "OPERAND_TYPE_FLOATACC",
360 { "OPERAND_TYPE_SREG2",
362 { "OPERAND_TYPE_SREG3",
364 { "OPERAND_TYPE_ACC",
366 { "OPERAND_TYPE_JUMPABSOLUTE",
368 { "OPERAND_TYPE_REGMMX",
370 { "OPERAND_TYPE_REGXMM",
372 { "OPERAND_TYPE_REGYMM",
374 { "OPERAND_TYPE_REGZMM",
376 { "OPERAND_TYPE_REGMASK",
378 { "OPERAND_TYPE_ESSEG",
380 { "OPERAND_TYPE_ACC32",
382 { "OPERAND_TYPE_ACC64",
384 { "OPERAND_TYPE_INOUTPORTREG",
386 { "OPERAND_TYPE_REG16_INOUTPORTREG",
387 "Reg16|InOutPortReg" },
388 { "OPERAND_TYPE_DISP16_32",
390 { "OPERAND_TYPE_ANYDISP",
391 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
392 { "OPERAND_TYPE_IMM16_32",
394 { "OPERAND_TYPE_IMM16_32S",
396 { "OPERAND_TYPE_IMM16_32_32S",
397 "Imm16|Imm32|Imm32S" },
398 { "OPERAND_TYPE_IMM32_64",
400 { "OPERAND_TYPE_IMM32_32S_DISP32",
401 "Imm32|Imm32S|Disp32" },
402 { "OPERAND_TYPE_IMM64_DISP64",
404 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
405 "Imm32|Imm32S|Imm64|Disp32" },
406 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
407 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
408 { "OPERAND_TYPE_VEC_IMM4",
410 { "OPERAND_TYPE_REGBND",
412 { "OPERAND_TYPE_VEC_DISP8",
416 typedef struct bitfield
423 #define BITFIELD(n) { n, 0, #n }
425 static bitfield cpu_flags[] =
433 BITFIELD (CpuClflush),
435 BITFIELD (CpuSYSCALL),
440 BITFIELD (CpuFISTTP),
446 BITFIELD (CpuSSE4_1),
447 BITFIELD (CpuSSE4_2),
450 BITFIELD (CpuAVX512F),
451 BITFIELD (CpuAVX512CD),
452 BITFIELD (CpuAVX512ER),
453 BITFIELD (CpuAVX512PF),
454 BITFIELD (CpuAVX512VL),
455 BITFIELD (CpuAVX512DQ),
456 BITFIELD (CpuAVX512BW),
462 BITFIELD (Cpu3dnowA),
463 BITFIELD (CpuPadLock),
469 BITFIELD (CpuXsaveopt),
471 BITFIELD (CpuPCLMUL),
482 BITFIELD (CpuRdtscp),
483 BITFIELD (CpuFSGSBase),
490 BITFIELD (CpuINVPCID),
491 BITFIELD (CpuVMFUNC),
492 BITFIELD (CpuRDSEED),
494 BITFIELD (CpuPRFCHW),
498 BITFIELD (CpuClflushOpt),
499 BITFIELD (CpuXSAVES),
500 BITFIELD (CpuXSAVEC),
501 BITFIELD (CpuPREFETCHWT1),
504 BITFIELD (CpuPCOMMIT),
508 BITFIELD (CpuAVX512IFMA),
509 BITFIELD (CpuAVX512VBMI),
510 BITFIELD (CpuMWAITX),
511 BITFIELD (CpuCLZERO),
514 BITFIELD (CpuRegMMX),
515 BITFIELD (CpuRegXMM),
516 BITFIELD (CpuRegYMM),
517 BITFIELD (CpuRegZMM),
518 BITFIELD (CpuRegMask),
520 BITFIELD (CpuUnused),
524 static bitfield opcode_modifiers[] =
530 BITFIELD (ShortForm),
532 BITFIELD (JumpDword),
534 BITFIELD (JumpInterSegment),
541 BITFIELD (CheckRegSize),
542 BITFIELD (IgnoreSize),
543 BITFIELD (DefaultSize),
552 BITFIELD (BNDPrefixOk),
553 BITFIELD (IsLockable),
554 BITFIELD (RegKludge),
555 BITFIELD (FirstXmm0),
556 BITFIELD (Implicit1stXmm0),
557 BITFIELD (RepPrefixOk),
558 BITFIELD (HLEPrefixOk),
561 BITFIELD (AddrPrefixOp0),
570 BITFIELD (VexOpcode),
571 BITFIELD (VexSources),
572 BITFIELD (VexImmExt),
579 BITFIELD (Broadcast),
580 BITFIELD (StaticRounding),
582 BITFIELD (Disp8MemShift),
583 BITFIELD (NoDefMask),
585 BITFIELD (ATTMnemonic),
586 BITFIELD (ATTSyntax),
587 BITFIELD (IntelSyntax),
592 static bitfield operand_types[] =
611 BITFIELD (BaseIndex),
617 BITFIELD (InOutPortReg),
618 BITFIELD (ShiftCount),
626 BITFIELD (JumpAbsolute),
639 BITFIELD (Unspecified),
643 BITFIELD (Vec_Disp8),
649 static const char *filename;
652 compare (const void *x, const void *y)
654 const bitfield *xp = (const bitfield *) x;
655 const bitfield *yp = (const bitfield *) y;
656 return xp->position - yp->position;
660 fail (const char *message, ...)
664 va_start (args, message);
665 fprintf (stderr, _("%s: Error: "), program_name);
666 vfprintf (stderr, message, args);
672 process_copyright (FILE *fp)
674 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
675 /* Copyright (C) 2007-2016 Free Software Foundation, Inc.\n\
677 This file is part of the GNU opcodes library.\n\
679 This library is free software; you can redistribute it and/or modify\n\
680 it under the terms of the GNU General Public License as published by\n\
681 the Free Software Foundation; either version 3, or (at your option)\n\
682 any later version.\n\
684 It is distributed in the hope that it will be useful, but WITHOUT\n\
685 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
686 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
687 License for more details.\n\
689 You should have received a copy of the GNU General Public License\n\
690 along with this program; if not, write to the Free Software\n\
691 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
692 MA 02110-1301, USA. */\n");
695 /* Remove leading white spaces. */
698 remove_leading_whitespaces (char *str)
700 while (ISSPACE (*str))
705 /* Remove trailing white spaces. */
708 remove_trailing_whitespaces (char *str)
710 size_t last = strlen (str);
718 if (ISSPACE (str [last]))
726 /* Find next field separated by SEP and terminate it. Return a
727 pointer to the one after it. */
730 next_field (char *str, char sep, char **next, char *last)
734 p = remove_leading_whitespaces (str);
735 for (str = p; *str != sep && *str != '\0'; str++);
738 remove_trailing_whitespaces (p);
748 static void set_bitfield (char *, bitfield *, int, unsigned int, int);
751 set_bitfield_from_cpu_flag_init (char *f, bitfield *array,
752 int value, unsigned int size,
755 char *str, *next, *last;
758 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
759 if (strcmp (cpu_flag_init[i].name, f) == 0)
761 /* Turn on selective bits. */
762 char *init = xstrdup (cpu_flag_init[i].init);
763 last = init + strlen (init);
764 for (next = init; next && next < last; )
766 str = next_field (next, '|', &next, last);
768 set_bitfield (str, array, 1, size, lineno);
778 set_bitfield (char *f, bitfield *array, int value,
779 unsigned int size, int lineno)
783 if (strcmp (f, "CpuFP") == 0)
785 set_bitfield("Cpu387", array, value, size, lineno);
786 set_bitfield("Cpu287", array, value, size, lineno);
789 else if (strcmp (f, "Mmword") == 0)
791 else if (strcmp (f, "Oword") == 0)
794 for (i = 0; i < size; i++)
795 if (strcasecmp (array[i].name, f) == 0)
797 array[i].value = value;
803 const char *v = strchr (f, '=');
810 for (i = 0; i < size; i++)
811 if (strncasecmp (array[i].name, f, n) == 0)
813 value = strtol (v + 1, &end, 0);
816 array[i].value = value;
824 /* Handle CPU_XXX_FLAGS. */
825 if (!set_bitfield_from_cpu_flag_init (f, array, value, size, lineno))
829 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
831 fail (_("Unknown bitfield: %s\n"), f);
835 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
836 int macro, const char *comma, const char *indent)
840 fprintf (table, "%s{ { ", indent);
842 for (i = 0; i < size - 1; i++)
844 if (((i + 1) % 20) != 0)
845 fprintf (table, "%d, ", flags[i].value);
847 fprintf (table, "%d,", flags[i].value);
848 if (((i + 1) % 20) == 0)
850 /* We need \\ for macro. */
852 fprintf (table, " \\\n %s", indent);
854 fprintf (table, "\n %s", indent);
858 fprintf (table, "%d } }%s\n", flags[i].value, comma);
862 process_i386_cpu_flag (FILE *table, char *flag, int macro,
863 const char *comma, const char *indent,
866 char *str, *next, *last;
868 bitfield flags [ARRAY_SIZE (cpu_flags)];
870 /* Copy the default cpu flags. */
871 memcpy (flags, cpu_flags, sizeof (cpu_flags));
873 if (strcasecmp (flag, "unknown") == 0)
875 /* We turn on everything except for cpu64 in case of
876 CPU_UNKNOWN_FLAGS. */
877 for (i = 0; i < ARRAY_SIZE (flags); i++)
878 if (flags[i].position != Cpu64)
881 else if (flag[0] == '~')
883 last = flag + strlen (flag);
890 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
897 /* First we turn on everything except for cpu64. */
898 for (i = 0; i < ARRAY_SIZE (flags); i++)
899 if (flags[i].position != Cpu64)
902 /* Turn off selective bits. */
903 for (; next && next < last; )
905 str = next_field (next, '|', &next, last);
907 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
910 else if (strcmp (flag, "0"))
912 /* Turn on selective bits. */
913 last = flag + strlen (flag);
914 for (next = flag; next && next < last; )
916 str = next_field (next, '|', &next, last);
918 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
922 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
927 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
931 fprintf (table, " { ");
933 for (i = 0; i < size - 1; i++)
935 if (((i + 1) % 20) != 0)
936 fprintf (table, "%d, ", modifier[i].value);
938 fprintf (table, "%d,", modifier[i].value);
939 if (((i + 1) % 20) == 0)
940 fprintf (table, "\n ");
943 fprintf (table, "%d },\n", modifier[i].value);
947 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
949 char *str, *next, *last;
950 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
952 /* Copy the default opcode modifier. */
953 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
955 if (strcmp (mod, "0"))
957 last = mod + strlen (mod);
958 for (next = mod; next && next < last; )
960 str = next_field (next, '|', &next, last);
962 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
966 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
970 output_operand_type (FILE *table, bitfield *types, unsigned int size,
971 int macro, const char *indent)
975 fprintf (table, "{ { ");
977 for (i = 0; i < size - 1; i++)
979 if (((i + 1) % 20) != 0)
980 fprintf (table, "%d, ", types[i].value);
982 fprintf (table, "%d,", types[i].value);
983 if (((i + 1) % 20) == 0)
985 /* We need \\ for macro. */
987 fprintf (table, " \\\n%s", indent);
989 fprintf (table, "\n%s", indent);
993 fprintf (table, "%d } }", types[i].value);
997 process_i386_operand_type (FILE *table, char *op, int macro,
998 const char *indent, int lineno)
1000 char *str, *next, *last;
1001 bitfield types [ARRAY_SIZE (operand_types)];
1003 /* Copy the default operand type. */
1004 memcpy (types, operand_types, sizeof (types));
1006 if (strcmp (op, "0"))
1008 last = op + strlen (op);
1009 for (next = op; next && next < last; )
1011 str = next_field (next, '|', &next, last);
1013 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1016 output_operand_type (table, types, ARRAY_SIZE (types), macro,
1021 output_i386_opcode (FILE *table, const char *name, char *str,
1022 char *last, int lineno)
1025 char *operands, *base_opcode, *extension_opcode, *opcode_length;
1026 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1028 /* Find number of operands. */
1029 operands = next_field (str, ',', &str, last);
1031 /* Find base_opcode. */
1032 base_opcode = next_field (str, ',', &str, last);
1034 /* Find extension_opcode. */
1035 extension_opcode = next_field (str, ',', &str, last);
1037 /* Find opcode_length. */
1038 opcode_length = next_field (str, ',', &str, last);
1040 /* Find cpu_flags. */
1041 cpu_flags = next_field (str, ',', &str, last);
1043 /* Find opcode_modifier. */
1044 opcode_modifier = next_field (str, ',', &str, last);
1046 /* Remove the first {. */
1047 str = remove_leading_whitespaces (str);
1050 str = remove_leading_whitespaces (str + 1);
1054 /* There are at least "X}". */
1058 /* Remove trailing white spaces and }. */
1062 if (ISSPACE (str[i]) || str[i] == '}')
1071 /* Find operand_types. */
1072 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1076 operand_types [i] = NULL;
1080 operand_types [i] = next_field (str, ',', &str, last);
1081 if (*operand_types[i] == '0')
1084 operand_types[i] = NULL;
1089 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
1090 name, operands, base_opcode, extension_opcode,
1093 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
1095 process_i386_opcode_modifier (table, opcode_modifier, lineno);
1097 fprintf (table, " { ");
1099 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1101 if (operand_types[i] == NULL || *operand_types[i] == '0')
1104 process_i386_operand_type (table, "0", 0, "\t ", lineno);
1109 fprintf (table, ",\n ");
1111 process_i386_operand_type (table, operand_types[i], 0,
1114 fprintf (table, " } },\n");
1117 struct opcode_hash_entry
1119 struct opcode_hash_entry *next;
1125 /* Calculate the hash value of an opcode hash entry P. */
1128 opcode_hash_hash (const void *p)
1130 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1131 return htab_hash_string (entry->name);
1134 /* Compare a string Q against an opcode hash entry P. */
1137 opcode_hash_eq (const void *p, const void *q)
1139 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1140 const char *name = (const char *) q;
1141 return strcmp (name, entry->name) == 0;
1145 process_i386_opcodes (FILE *table)
1150 char *str, *p, *last, *name;
1151 struct opcode_hash_entry **hash_slot, **entry, *next;
1152 htab_t opcode_hash_table;
1153 struct opcode_hash_entry **opcode_array;
1154 unsigned int opcode_array_size = 1024;
1157 filename = "i386-opc.tbl";
1158 fp = fopen (filename, "r");
1161 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1165 opcode_array = (struct opcode_hash_entry **)
1166 xmalloc (sizeof (*opcode_array) * opcode_array_size);
1168 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1169 opcode_hash_eq, NULL,
1172 fprintf (table, "\n/* i386 opcode table. */\n\n");
1173 fprintf (table, "const insn_template i386_optab[] =\n{\n");
1175 /* Put everything on opcode array. */
1178 if (fgets (buf, sizeof (buf), fp) == NULL)
1183 p = remove_leading_whitespaces (buf);
1185 /* Skip comments. */
1186 str = strstr (p, "//");
1190 /* Remove trailing white spaces. */
1191 remove_trailing_whitespaces (p);
1196 /* Ignore comments. */
1204 last = p + strlen (p);
1207 name = next_field (p, ',', &str, last);
1209 /* Get the slot in hash table. */
1210 hash_slot = (struct opcode_hash_entry **)
1211 htab_find_slot_with_hash (opcode_hash_table, name,
1212 htab_hash_string (name),
1215 if (*hash_slot == NULL)
1217 /* It is the new one. Put it on opcode array. */
1218 if (i >= opcode_array_size)
1220 /* Grow the opcode array when needed. */
1221 opcode_array_size += 1024;
1222 opcode_array = (struct opcode_hash_entry **)
1223 xrealloc (opcode_array,
1224 sizeof (*opcode_array) * opcode_array_size);
1227 opcode_array[i] = (struct opcode_hash_entry *)
1228 xmalloc (sizeof (struct opcode_hash_entry));
1229 opcode_array[i]->next = NULL;
1230 opcode_array[i]->name = xstrdup (name);
1231 opcode_array[i]->opcode = xstrdup (str);
1232 opcode_array[i]->lineno = lineno;
1233 *hash_slot = opcode_array[i];
1238 /* Append it to the existing one. */
1240 while ((*entry) != NULL)
1241 entry = &(*entry)->next;
1242 *entry = (struct opcode_hash_entry *)
1243 xmalloc (sizeof (struct opcode_hash_entry));
1244 (*entry)->next = NULL;
1245 (*entry)->name = (*hash_slot)->name;
1246 (*entry)->opcode = xstrdup (str);
1247 (*entry)->lineno = lineno;
1251 /* Process opcode array. */
1252 for (j = 0; j < i; j++)
1254 for (next = opcode_array[j]; next; next = next->next)
1258 lineno = next->lineno;
1259 last = str + strlen (str);
1260 output_i386_opcode (table, name, str, last, lineno);
1266 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1268 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1270 process_i386_opcode_modifier (table, "0", -1);
1272 fprintf (table, " { ");
1273 process_i386_operand_type (table, "0", 0, "\t ", -1);
1274 fprintf (table, " } }\n");
1276 fprintf (table, "};\n");
1280 process_i386_registers (FILE *table)
1284 char *str, *p, *last;
1285 char *reg_name, *reg_type, *reg_flags, *reg_num;
1286 char *dw2_32_num, *dw2_64_num;
1289 filename = "i386-reg.tbl";
1290 fp = fopen (filename, "r");
1292 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1295 fprintf (table, "\n/* i386 register table. */\n\n");
1296 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1300 if (fgets (buf, sizeof (buf), fp) == NULL)
1305 p = remove_leading_whitespaces (buf);
1307 /* Skip comments. */
1308 str = strstr (p, "//");
1312 /* Remove trailing white spaces. */
1313 remove_trailing_whitespaces (p);
1318 fprintf (table, "%s\n", p);
1326 last = p + strlen (p);
1328 /* Find reg_name. */
1329 reg_name = next_field (p, ',', &str, last);
1331 /* Find reg_type. */
1332 reg_type = next_field (str, ',', &str, last);
1334 /* Find reg_flags. */
1335 reg_flags = next_field (str, ',', &str, last);
1338 reg_num = next_field (str, ',', &str, last);
1340 fprintf (table, " { \"%s\",\n ", reg_name);
1342 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1344 /* Find 32-bit Dwarf2 register number. */
1345 dw2_32_num = next_field (str, ',', &str, last);
1347 /* Find 64-bit Dwarf2 register number. */
1348 dw2_64_num = next_field (str, ',', &str, last);
1350 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1351 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1356 fprintf (table, "};\n");
1358 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1362 process_i386_initializers (void)
1365 FILE *fp = fopen ("i386-init.h", "w");
1369 fail (_("can't create i386-init.h, errno = %s\n"),
1372 process_copyright (fp);
1374 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1376 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1377 init = xstrdup (cpu_flag_init[i].init);
1378 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1382 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1384 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1385 init = xstrdup (operand_type_init[i].init);
1386 process_i386_operand_type (fp, init, 1, " ", -1);
1394 /* Program options. */
1395 #define OPTION_SRCDIR 200
1397 struct option long_options[] =
1399 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1400 {"debug", no_argument, NULL, 'd'},
1401 {"version", no_argument, NULL, 'V'},
1402 {"help", no_argument, NULL, 'h'},
1403 {0, no_argument, NULL, 0}
1407 print_version (void)
1409 printf ("%s: version 1.0\n", program_name);
1414 usage (FILE * stream, int status)
1416 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1422 main (int argc, char **argv)
1424 extern int chdir (char *);
1425 char *srcdir = NULL;
1427 unsigned int i, cpumax;
1430 program_name = *argv;
1431 xmalloc_set_program_name (program_name);
1433 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1458 if (chdir (srcdir) != 0)
1459 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1460 srcdir, xstrerror (errno));
1462 /* cpu_flags isn't sorted by position. */
1464 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
1465 if (cpu_flags[i].position > cpumax)
1466 cpumax = cpu_flags[i].position;
1468 /* Check the unused bitfield in i386_cpu_flags. */
1470 if ((cpumax - 1) != CpuMax)
1471 fail (_("CpuMax != %d!\n"), cpumax);
1473 if (cpumax != CpuMax)
1474 fail (_("CpuMax != %d!\n"), cpumax);
1476 c = CpuNumOfBits - CpuMax - 1;
1478 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1481 /* Check the unused bitfield in i386_operand_type. */
1483 c = OTNumOfBits - OTMax - 1;
1485 fail (_("%d unused bits in i386_operand_type.\n"), c);
1488 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1491 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1492 sizeof (opcode_modifiers [0]), compare);
1494 qsort (operand_types, ARRAY_SIZE (operand_types),
1495 sizeof (operand_types [0]), compare);
1497 table = fopen ("i386-tbl.h", "w");
1499 fail (_("can't create i386-tbl.h, errno = %s\n"),
1502 process_copyright (table);
1504 process_i386_opcodes (table);
1505 process_i386_registers (table);
1506 process_i386_initializers ();