1 /* Copyright (C) 2007-2017 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" },
220 { "CPU_AVX512_4FMAPS_FLAGS",
221 "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
222 { "CPU_AVX512_4VNNIW_FLAGS",
223 "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
224 { "CPU_AVX512_VPOPCNTDQ_FLAGS",
225 "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
231 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
234 { "CPU_RDSEED_FLAGS",
236 { "CPU_PRFCHW_FLAGS",
243 "CPU_SSE2_FLAGS|CpuSHA" },
244 { "CPU_CLFLUSHOPT_FLAGS",
246 { "CPU_XSAVES_FLAGS",
247 "CPU_XSAVE_FLAGS|CpuXSAVES" },
248 { "CPU_XSAVEC_FLAGS",
249 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
250 { "CPU_PREFETCHWT1_FLAGS",
256 { "CPU_CLZERO_FLAGS",
258 { "CPU_MWAITX_FLAGS",
264 { "CPU_PTWRITE_FLAGS",
266 { "CPU_ANY_X87_FLAGS",
267 "CPU_ANY_287_FLAGS|Cpu8087" },
268 { "CPU_ANY_287_FLAGS",
269 "CPU_ANY_387_FLAGS|Cpu287" },
270 { "CPU_ANY_387_FLAGS",
271 "CPU_ANY_687_FLAGS|Cpu387" },
272 { "CPU_ANY_687_FLAGS",
273 "Cpu687|CpuFISTTP" },
274 { "CPU_ANY_MMX_FLAGS",
275 "CPU_3DNOWA_FLAGS" },
276 { "CPU_ANY_SSE_FLAGS",
277 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
278 { "CPU_ANY_SSE2_FLAGS",
279 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
280 { "CPU_ANY_SSE3_FLAGS",
281 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
282 { "CPU_ANY_SSSE3_FLAGS",
283 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
284 { "CPU_ANY_SSE4_1_FLAGS",
285 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
286 { "CPU_ANY_SSE4_2_FLAGS",
288 { "CPU_ANY_AVX_FLAGS",
289 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
290 { "CPU_ANY_AVX2_FLAGS",
292 { "CPU_ANY_AVX512F_FLAGS",
293 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512F" },
294 { "CPU_ANY_AVX512CD_FLAGS",
296 { "CPU_ANY_AVX512ER_FLAGS",
298 { "CPU_ANY_AVX512PF_FLAGS",
300 { "CPU_ANY_AVX512DQ_FLAGS",
302 { "CPU_ANY_AVX512BW_FLAGS",
304 { "CPU_ANY_AVX512VL_FLAGS",
306 { "CPU_ANY_AVX512IFMA_FLAGS",
308 { "CPU_ANY_AVX512VBMI_FLAGS",
310 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
311 "CpuAVX512_4FMAPS" },
312 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
313 "CpuAVX512_4VNNIW" },
314 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
315 "CpuAVX512_VPOPCNTDQ" },
318 static initializer operand_type_init[] =
320 { "OPERAND_TYPE_NONE",
322 { "OPERAND_TYPE_REG8",
324 { "OPERAND_TYPE_REG16",
326 { "OPERAND_TYPE_REG32",
328 { "OPERAND_TYPE_REG64",
330 { "OPERAND_TYPE_IMM1",
332 { "OPERAND_TYPE_IMM8",
334 { "OPERAND_TYPE_IMM8S",
336 { "OPERAND_TYPE_IMM16",
338 { "OPERAND_TYPE_IMM32",
340 { "OPERAND_TYPE_IMM32S",
342 { "OPERAND_TYPE_IMM64",
344 { "OPERAND_TYPE_BASEINDEX",
346 { "OPERAND_TYPE_DISP8",
348 { "OPERAND_TYPE_DISP16",
350 { "OPERAND_TYPE_DISP32",
352 { "OPERAND_TYPE_DISP32S",
354 { "OPERAND_TYPE_DISP64",
356 { "OPERAND_TYPE_INOUTPORTREG",
358 { "OPERAND_TYPE_SHIFTCOUNT",
360 { "OPERAND_TYPE_CONTROL",
362 { "OPERAND_TYPE_TEST",
364 { "OPERAND_TYPE_DEBUG",
366 { "OPERAND_TYPE_FLOATREG",
368 { "OPERAND_TYPE_FLOATACC",
370 { "OPERAND_TYPE_SREG2",
372 { "OPERAND_TYPE_SREG3",
374 { "OPERAND_TYPE_ACC",
376 { "OPERAND_TYPE_JUMPABSOLUTE",
378 { "OPERAND_TYPE_REGMMX",
380 { "OPERAND_TYPE_REGXMM",
382 { "OPERAND_TYPE_REGYMM",
384 { "OPERAND_TYPE_REGZMM",
386 { "OPERAND_TYPE_REGMASK",
388 { "OPERAND_TYPE_ESSEG",
390 { "OPERAND_TYPE_ACC32",
392 { "OPERAND_TYPE_ACC64",
394 { "OPERAND_TYPE_INOUTPORTREG",
396 { "OPERAND_TYPE_REG16_INOUTPORTREG",
397 "Reg16|InOutPortReg" },
398 { "OPERAND_TYPE_DISP16_32",
400 { "OPERAND_TYPE_ANYDISP",
401 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
402 { "OPERAND_TYPE_IMM16_32",
404 { "OPERAND_TYPE_IMM16_32S",
406 { "OPERAND_TYPE_IMM16_32_32S",
407 "Imm16|Imm32|Imm32S" },
408 { "OPERAND_TYPE_IMM32_64",
410 { "OPERAND_TYPE_IMM32_32S_DISP32",
411 "Imm32|Imm32S|Disp32" },
412 { "OPERAND_TYPE_IMM64_DISP64",
414 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
415 "Imm32|Imm32S|Imm64|Disp32" },
416 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
417 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
418 { "OPERAND_TYPE_VEC_IMM4",
420 { "OPERAND_TYPE_REGBND",
422 { "OPERAND_TYPE_VEC_DISP8",
426 typedef struct bitfield
433 #define BITFIELD(n) { n, 0, #n }
435 static bitfield cpu_flags[] =
443 BITFIELD (CpuClflush),
445 BITFIELD (CpuSYSCALL),
450 BITFIELD (CpuFISTTP),
456 BITFIELD (CpuSSE4_1),
457 BITFIELD (CpuSSE4_2),
460 BITFIELD (CpuAVX512F),
461 BITFIELD (CpuAVX512CD),
462 BITFIELD (CpuAVX512ER),
463 BITFIELD (CpuAVX512PF),
464 BITFIELD (CpuAVX512VL),
465 BITFIELD (CpuAVX512DQ),
466 BITFIELD (CpuAVX512BW),
472 BITFIELD (Cpu3dnowA),
473 BITFIELD (CpuPadLock),
479 BITFIELD (CpuXsaveopt),
481 BITFIELD (CpuPCLMUL),
492 BITFIELD (CpuRdtscp),
493 BITFIELD (CpuFSGSBase),
500 BITFIELD (CpuINVPCID),
501 BITFIELD (CpuVMFUNC),
502 BITFIELD (CpuRDSEED),
504 BITFIELD (CpuPRFCHW),
508 BITFIELD (CpuClflushOpt),
509 BITFIELD (CpuXSAVES),
510 BITFIELD (CpuXSAVEC),
511 BITFIELD (CpuPREFETCHWT1),
517 BITFIELD (CpuAVX512IFMA),
518 BITFIELD (CpuAVX512VBMI),
519 BITFIELD (CpuAVX512_4FMAPS),
520 BITFIELD (CpuAVX512_4VNNIW),
521 BITFIELD (CpuAVX512_VPOPCNTDQ),
522 BITFIELD (CpuMWAITX),
523 BITFIELD (CpuCLZERO),
526 BITFIELD (CpuPTWRITE),
527 BITFIELD (CpuRegMMX),
528 BITFIELD (CpuRegXMM),
529 BITFIELD (CpuRegYMM),
530 BITFIELD (CpuRegZMM),
531 BITFIELD (CpuRegMask),
533 BITFIELD (CpuUnused),
537 static bitfield opcode_modifiers[] =
543 BITFIELD (ShortForm),
545 BITFIELD (JumpDword),
547 BITFIELD (JumpInterSegment),
554 BITFIELD (CheckRegSize),
555 BITFIELD (IgnoreSize),
556 BITFIELD (DefaultSize),
565 BITFIELD (BNDPrefixOk),
566 BITFIELD (IsLockable),
567 BITFIELD (RegKludge),
568 BITFIELD (FirstXmm0),
569 BITFIELD (Implicit1stXmm0),
570 BITFIELD (RepPrefixOk),
571 BITFIELD (HLEPrefixOk),
574 BITFIELD (AddrPrefixOp0),
583 BITFIELD (VexOpcode),
584 BITFIELD (VexSources),
585 BITFIELD (VexImmExt),
592 BITFIELD (Broadcast),
593 BITFIELD (StaticRounding),
595 BITFIELD (Disp8MemShift),
596 BITFIELD (NoDefMask),
597 BITFIELD (ImplicitQuadGroup),
599 BITFIELD (ATTMnemonic),
600 BITFIELD (ATTSyntax),
601 BITFIELD (IntelSyntax),
606 static bitfield operand_types[] =
625 BITFIELD (BaseIndex),
631 BITFIELD (InOutPortReg),
632 BITFIELD (ShiftCount),
640 BITFIELD (JumpAbsolute),
653 BITFIELD (Unspecified),
657 BITFIELD (Vec_Disp8),
663 static const char *filename;
666 compare (const void *x, const void *y)
668 const bitfield *xp = (const bitfield *) x;
669 const bitfield *yp = (const bitfield *) y;
670 return xp->position - yp->position;
674 fail (const char *message, ...)
678 va_start (args, message);
679 fprintf (stderr, _("%s: Error: "), program_name);
680 vfprintf (stderr, message, args);
686 process_copyright (FILE *fp)
688 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
689 /* Copyright (C) 2007-2017 Free Software Foundation, Inc.\n\
691 This file is part of the GNU opcodes library.\n\
693 This library is free software; you can redistribute it and/or modify\n\
694 it under the terms of the GNU General Public License as published by\n\
695 the Free Software Foundation; either version 3, or (at your option)\n\
696 any later version.\n\
698 It is distributed in the hope that it will be useful, but WITHOUT\n\
699 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
700 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
701 License for more details.\n\
703 You should have received a copy of the GNU General Public License\n\
704 along with this program; if not, write to the Free Software\n\
705 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
706 MA 02110-1301, USA. */\n");
709 /* Remove leading white spaces. */
712 remove_leading_whitespaces (char *str)
714 while (ISSPACE (*str))
719 /* Remove trailing white spaces. */
722 remove_trailing_whitespaces (char *str)
724 size_t last = strlen (str);
732 if (ISSPACE (str [last]))
740 /* Find next field separated by SEP and terminate it. Return a
741 pointer to the one after it. */
744 next_field (char *str, char sep, char **next, char *last)
748 p = remove_leading_whitespaces (str);
749 for (str = p; *str != sep && *str != '\0'; str++);
752 remove_trailing_whitespaces (p);
762 static void set_bitfield (char *, bitfield *, int, unsigned int, int);
765 set_bitfield_from_cpu_flag_init (char *f, bitfield *array,
766 int value, unsigned int size,
769 char *str, *next, *last;
772 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
773 if (strcmp (cpu_flag_init[i].name, f) == 0)
775 /* Turn on selective bits. */
776 char *init = xstrdup (cpu_flag_init[i].init);
777 last = init + strlen (init);
778 for (next = init; next && next < last; )
780 str = next_field (next, '|', &next, last);
782 set_bitfield (str, array, 1, size, lineno);
792 set_bitfield (char *f, bitfield *array, int value,
793 unsigned int size, int lineno)
797 if (strcmp (f, "CpuFP") == 0)
799 set_bitfield("Cpu387", array, value, size, lineno);
800 set_bitfield("Cpu287", array, value, size, lineno);
803 else if (strcmp (f, "Mmword") == 0)
805 else if (strcmp (f, "Oword") == 0)
808 for (i = 0; i < size; i++)
809 if (strcasecmp (array[i].name, f) == 0)
811 array[i].value = value;
817 const char *v = strchr (f, '=');
824 for (i = 0; i < size; i++)
825 if (strncasecmp (array[i].name, f, n) == 0)
827 value = strtol (v + 1, &end, 0);
830 array[i].value = value;
838 /* Handle CPU_XXX_FLAGS. */
839 if (!set_bitfield_from_cpu_flag_init (f, array, value, size, lineno))
843 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
845 fail (_("Unknown bitfield: %s\n"), f);
849 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
850 int macro, const char *comma, const char *indent)
854 fprintf (table, "%s{ { ", indent);
856 for (i = 0; i < size - 1; i++)
858 if (((i + 1) % 20) != 0)
859 fprintf (table, "%d, ", flags[i].value);
861 fprintf (table, "%d,", flags[i].value);
862 if (((i + 1) % 20) == 0)
864 /* We need \\ for macro. */
866 fprintf (table, " \\\n %s", indent);
868 fprintf (table, "\n %s", indent);
872 fprintf (table, "%d } }%s\n", flags[i].value, comma);
876 process_i386_cpu_flag (FILE *table, char *flag, int macro,
877 const char *comma, const char *indent,
880 char *str, *next, *last;
882 bitfield flags [ARRAY_SIZE (cpu_flags)];
884 /* Copy the default cpu flags. */
885 memcpy (flags, cpu_flags, sizeof (cpu_flags));
887 if (strcasecmp (flag, "unknown") == 0)
889 /* We turn on everything except for cpu64 in case of
890 CPU_UNKNOWN_FLAGS. */
891 for (i = 0; i < ARRAY_SIZE (flags); i++)
892 if (flags[i].position != Cpu64)
895 else if (flag[0] == '~')
897 last = flag + strlen (flag);
904 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
911 /* First we turn on everything except for cpu64. */
912 for (i = 0; i < ARRAY_SIZE (flags); i++)
913 if (flags[i].position != Cpu64)
916 /* Turn off selective bits. */
917 for (; next && next < last; )
919 str = next_field (next, '|', &next, last);
921 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
924 else if (strcmp (flag, "0"))
926 /* Turn on selective bits. */
927 last = flag + strlen (flag);
928 for (next = flag; next && next < last; )
930 str = next_field (next, '|', &next, last);
932 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
936 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
941 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
945 fprintf (table, " { ");
947 for (i = 0; i < size - 1; i++)
949 if (((i + 1) % 20) != 0)
950 fprintf (table, "%d, ", modifier[i].value);
952 fprintf (table, "%d,", modifier[i].value);
953 if (((i + 1) % 20) == 0)
954 fprintf (table, "\n ");
957 fprintf (table, "%d },\n", modifier[i].value);
961 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
963 char *str, *next, *last;
964 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
966 /* Copy the default opcode modifier. */
967 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
969 if (strcmp (mod, "0"))
971 last = mod + strlen (mod);
972 for (next = mod; next && next < last; )
974 str = next_field (next, '|', &next, last);
976 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
980 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
984 output_operand_type (FILE *table, bitfield *types, unsigned int size,
985 int macro, const char *indent)
989 fprintf (table, "{ { ");
991 for (i = 0; i < size - 1; i++)
993 if (((i + 1) % 20) != 0)
994 fprintf (table, "%d, ", types[i].value);
996 fprintf (table, "%d,", types[i].value);
997 if (((i + 1) % 20) == 0)
999 /* We need \\ for macro. */
1001 fprintf (table, " \\\n%s", indent);
1003 fprintf (table, "\n%s", indent);
1007 fprintf (table, "%d } }", types[i].value);
1011 process_i386_operand_type (FILE *table, char *op, int macro,
1012 const char *indent, int lineno)
1014 char *str, *next, *last;
1015 bitfield types [ARRAY_SIZE (operand_types)];
1017 /* Copy the default operand type. */
1018 memcpy (types, operand_types, sizeof (types));
1020 if (strcmp (op, "0"))
1022 last = op + strlen (op);
1023 for (next = op; next && next < last; )
1025 str = next_field (next, '|', &next, last);
1027 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1030 output_operand_type (table, types, ARRAY_SIZE (types), macro,
1035 output_i386_opcode (FILE *table, const char *name, char *str,
1036 char *last, int lineno)
1039 char *operands, *base_opcode, *extension_opcode, *opcode_length;
1040 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1042 /* Find number of operands. */
1043 operands = next_field (str, ',', &str, last);
1045 /* Find base_opcode. */
1046 base_opcode = next_field (str, ',', &str, last);
1048 /* Find extension_opcode. */
1049 extension_opcode = next_field (str, ',', &str, last);
1051 /* Find opcode_length. */
1052 opcode_length = next_field (str, ',', &str, last);
1054 /* Find cpu_flags. */
1055 cpu_flags = next_field (str, ',', &str, last);
1057 /* Find opcode_modifier. */
1058 opcode_modifier = next_field (str, ',', &str, last);
1060 /* Remove the first {. */
1061 str = remove_leading_whitespaces (str);
1064 str = remove_leading_whitespaces (str + 1);
1068 /* There are at least "X}". */
1072 /* Remove trailing white spaces and }. */
1076 if (ISSPACE (str[i]) || str[i] == '}')
1085 /* Find operand_types. */
1086 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1090 operand_types [i] = NULL;
1094 operand_types [i] = next_field (str, ',', &str, last);
1095 if (*operand_types[i] == '0')
1098 operand_types[i] = NULL;
1103 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
1104 name, operands, base_opcode, extension_opcode,
1107 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
1109 process_i386_opcode_modifier (table, opcode_modifier, lineno);
1111 fprintf (table, " { ");
1113 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1115 if (operand_types[i] == NULL || *operand_types[i] == '0')
1118 process_i386_operand_type (table, "0", 0, "\t ", lineno);
1123 fprintf (table, ",\n ");
1125 process_i386_operand_type (table, operand_types[i], 0,
1128 fprintf (table, " } },\n");
1131 struct opcode_hash_entry
1133 struct opcode_hash_entry *next;
1139 /* Calculate the hash value of an opcode hash entry P. */
1142 opcode_hash_hash (const void *p)
1144 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1145 return htab_hash_string (entry->name);
1148 /* Compare a string Q against an opcode hash entry P. */
1151 opcode_hash_eq (const void *p, const void *q)
1153 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1154 const char *name = (const char *) q;
1155 return strcmp (name, entry->name) == 0;
1159 process_i386_opcodes (FILE *table)
1164 char *str, *p, *last, *name;
1165 struct opcode_hash_entry **hash_slot, **entry, *next;
1166 htab_t opcode_hash_table;
1167 struct opcode_hash_entry **opcode_array;
1168 unsigned int opcode_array_size = 1024;
1171 filename = "i386-opc.tbl";
1172 fp = fopen (filename, "r");
1175 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1179 opcode_array = (struct opcode_hash_entry **)
1180 xmalloc (sizeof (*opcode_array) * opcode_array_size);
1182 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1183 opcode_hash_eq, NULL,
1186 fprintf (table, "\n/* i386 opcode table. */\n\n");
1187 fprintf (table, "const insn_template i386_optab[] =\n{\n");
1189 /* Put everything on opcode array. */
1192 if (fgets (buf, sizeof (buf), fp) == NULL)
1197 p = remove_leading_whitespaces (buf);
1199 /* Skip comments. */
1200 str = strstr (p, "//");
1204 /* Remove trailing white spaces. */
1205 remove_trailing_whitespaces (p);
1210 /* Ignore comments. */
1218 last = p + strlen (p);
1221 name = next_field (p, ',', &str, last);
1223 /* Get the slot in hash table. */
1224 hash_slot = (struct opcode_hash_entry **)
1225 htab_find_slot_with_hash (opcode_hash_table, name,
1226 htab_hash_string (name),
1229 if (*hash_slot == NULL)
1231 /* It is the new one. Put it on opcode array. */
1232 if (i >= opcode_array_size)
1234 /* Grow the opcode array when needed. */
1235 opcode_array_size += 1024;
1236 opcode_array = (struct opcode_hash_entry **)
1237 xrealloc (opcode_array,
1238 sizeof (*opcode_array) * opcode_array_size);
1241 opcode_array[i] = (struct opcode_hash_entry *)
1242 xmalloc (sizeof (struct opcode_hash_entry));
1243 opcode_array[i]->next = NULL;
1244 opcode_array[i]->name = xstrdup (name);
1245 opcode_array[i]->opcode = xstrdup (str);
1246 opcode_array[i]->lineno = lineno;
1247 *hash_slot = opcode_array[i];
1252 /* Append it to the existing one. */
1254 while ((*entry) != NULL)
1255 entry = &(*entry)->next;
1256 *entry = (struct opcode_hash_entry *)
1257 xmalloc (sizeof (struct opcode_hash_entry));
1258 (*entry)->next = NULL;
1259 (*entry)->name = (*hash_slot)->name;
1260 (*entry)->opcode = xstrdup (str);
1261 (*entry)->lineno = lineno;
1265 /* Process opcode array. */
1266 for (j = 0; j < i; j++)
1268 for (next = opcode_array[j]; next; next = next->next)
1272 lineno = next->lineno;
1273 last = str + strlen (str);
1274 output_i386_opcode (table, name, str, last, lineno);
1280 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1282 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1284 process_i386_opcode_modifier (table, "0", -1);
1286 fprintf (table, " { ");
1287 process_i386_operand_type (table, "0", 0, "\t ", -1);
1288 fprintf (table, " } }\n");
1290 fprintf (table, "};\n");
1294 process_i386_registers (FILE *table)
1298 char *str, *p, *last;
1299 char *reg_name, *reg_type, *reg_flags, *reg_num;
1300 char *dw2_32_num, *dw2_64_num;
1303 filename = "i386-reg.tbl";
1304 fp = fopen (filename, "r");
1306 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1309 fprintf (table, "\n/* i386 register table. */\n\n");
1310 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1314 if (fgets (buf, sizeof (buf), fp) == NULL)
1319 p = remove_leading_whitespaces (buf);
1321 /* Skip comments. */
1322 str = strstr (p, "//");
1326 /* Remove trailing white spaces. */
1327 remove_trailing_whitespaces (p);
1332 fprintf (table, "%s\n", p);
1340 last = p + strlen (p);
1342 /* Find reg_name. */
1343 reg_name = next_field (p, ',', &str, last);
1345 /* Find reg_type. */
1346 reg_type = next_field (str, ',', &str, last);
1348 /* Find reg_flags. */
1349 reg_flags = next_field (str, ',', &str, last);
1352 reg_num = next_field (str, ',', &str, last);
1354 fprintf (table, " { \"%s\",\n ", reg_name);
1356 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1358 /* Find 32-bit Dwarf2 register number. */
1359 dw2_32_num = next_field (str, ',', &str, last);
1361 /* Find 64-bit Dwarf2 register number. */
1362 dw2_64_num = next_field (str, ',', &str, last);
1364 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1365 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1370 fprintf (table, "};\n");
1372 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1376 process_i386_initializers (void)
1379 FILE *fp = fopen ("i386-init.h", "w");
1383 fail (_("can't create i386-init.h, errno = %s\n"),
1386 process_copyright (fp);
1388 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1390 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1391 init = xstrdup (cpu_flag_init[i].init);
1392 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1396 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1398 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1399 init = xstrdup (operand_type_init[i].init);
1400 process_i386_operand_type (fp, init, 1, " ", -1);
1408 /* Program options. */
1409 #define OPTION_SRCDIR 200
1411 struct option long_options[] =
1413 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1414 {"debug", no_argument, NULL, 'd'},
1415 {"version", no_argument, NULL, 'V'},
1416 {"help", no_argument, NULL, 'h'},
1417 {0, no_argument, NULL, 0}
1421 print_version (void)
1423 printf ("%s: version 1.0\n", program_name);
1428 usage (FILE * stream, int status)
1430 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1436 main (int argc, char **argv)
1438 extern int chdir (char *);
1439 char *srcdir = NULL;
1441 unsigned int i, cpumax;
1444 program_name = *argv;
1445 xmalloc_set_program_name (program_name);
1447 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1472 if (chdir (srcdir) != 0)
1473 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1474 srcdir, xstrerror (errno));
1476 /* cpu_flags isn't sorted by position. */
1478 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
1479 if (cpu_flags[i].position > cpumax)
1480 cpumax = cpu_flags[i].position;
1482 /* Check the unused bitfield in i386_cpu_flags. */
1484 if ((cpumax - 1) != CpuMax)
1485 fail (_("CpuMax != %d!\n"), cpumax);
1487 if (cpumax != CpuMax)
1488 fail (_("CpuMax != %d!\n"), cpumax);
1490 c = CpuNumOfBits - CpuMax - 1;
1492 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1495 /* Check the unused bitfield in i386_operand_type. */
1497 c = OTNumOfBits - OTMax - 1;
1499 fail (_("%d unused bits in i386_operand_type.\n"), c);
1502 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1505 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1506 sizeof (opcode_modifiers [0]), compare);
1508 qsort (operand_types, ARRAY_SIZE (operand_types),
1509 sizeof (operand_types [0]), compare);
1511 table = fopen ("i386-tbl.h", "w");
1513 fail (_("can't create i386-tbl.h, errno = %s\n"),
1516 process_copyright (table);
1518 process_i386_opcodes (table);
1519 process_i386_registers (table);
1520 process_i386_initializers ();