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",
268 { "CPU_ANY_X87_FLAGS",
269 "CPU_ANY_287_FLAGS|Cpu8087" },
270 { "CPU_ANY_287_FLAGS",
271 "CPU_ANY_387_FLAGS|Cpu287" },
272 { "CPU_ANY_387_FLAGS",
273 "CPU_ANY_687_FLAGS|Cpu387" },
274 { "CPU_ANY_687_FLAGS",
275 "Cpu687|CpuFISTTP" },
276 { "CPU_ANY_MMX_FLAGS",
277 "CPU_3DNOWA_FLAGS" },
278 { "CPU_ANY_SSE_FLAGS",
279 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
280 { "CPU_ANY_SSE2_FLAGS",
281 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
282 { "CPU_ANY_SSE3_FLAGS",
283 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
284 { "CPU_ANY_SSSE3_FLAGS",
285 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
286 { "CPU_ANY_SSE4_1_FLAGS",
287 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
288 { "CPU_ANY_SSE4_2_FLAGS",
290 { "CPU_ANY_AVX_FLAGS",
291 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
292 { "CPU_ANY_AVX2_FLAGS",
294 { "CPU_ANY_AVX512F_FLAGS",
295 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512F" },
296 { "CPU_ANY_AVX512CD_FLAGS",
298 { "CPU_ANY_AVX512ER_FLAGS",
300 { "CPU_ANY_AVX512PF_FLAGS",
302 { "CPU_ANY_AVX512DQ_FLAGS",
304 { "CPU_ANY_AVX512BW_FLAGS",
306 { "CPU_ANY_AVX512VL_FLAGS",
308 { "CPU_ANY_AVX512IFMA_FLAGS",
310 { "CPU_ANY_AVX512VBMI_FLAGS",
312 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
313 "CpuAVX512_4FMAPS" },
314 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
315 "CpuAVX512_4VNNIW" },
316 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
317 "CpuAVX512_VPOPCNTDQ" },
320 static initializer operand_type_init[] =
322 { "OPERAND_TYPE_NONE",
324 { "OPERAND_TYPE_REG8",
326 { "OPERAND_TYPE_REG16",
328 { "OPERAND_TYPE_REG32",
330 { "OPERAND_TYPE_REG64",
332 { "OPERAND_TYPE_IMM1",
334 { "OPERAND_TYPE_IMM8",
336 { "OPERAND_TYPE_IMM8S",
338 { "OPERAND_TYPE_IMM16",
340 { "OPERAND_TYPE_IMM32",
342 { "OPERAND_TYPE_IMM32S",
344 { "OPERAND_TYPE_IMM64",
346 { "OPERAND_TYPE_BASEINDEX",
348 { "OPERAND_TYPE_DISP8",
350 { "OPERAND_TYPE_DISP16",
352 { "OPERAND_TYPE_DISP32",
354 { "OPERAND_TYPE_DISP32S",
356 { "OPERAND_TYPE_DISP64",
358 { "OPERAND_TYPE_INOUTPORTREG",
360 { "OPERAND_TYPE_SHIFTCOUNT",
362 { "OPERAND_TYPE_CONTROL",
364 { "OPERAND_TYPE_TEST",
366 { "OPERAND_TYPE_DEBUG",
368 { "OPERAND_TYPE_FLOATREG",
370 { "OPERAND_TYPE_FLOATACC",
372 { "OPERAND_TYPE_SREG2",
374 { "OPERAND_TYPE_SREG3",
376 { "OPERAND_TYPE_ACC",
378 { "OPERAND_TYPE_JUMPABSOLUTE",
380 { "OPERAND_TYPE_REGMMX",
382 { "OPERAND_TYPE_REGXMM",
384 { "OPERAND_TYPE_REGYMM",
386 { "OPERAND_TYPE_REGZMM",
388 { "OPERAND_TYPE_REGMASK",
390 { "OPERAND_TYPE_ESSEG",
392 { "OPERAND_TYPE_ACC32",
394 { "OPERAND_TYPE_ACC64",
396 { "OPERAND_TYPE_INOUTPORTREG",
398 { "OPERAND_TYPE_REG16_INOUTPORTREG",
399 "Reg16|InOutPortReg" },
400 { "OPERAND_TYPE_DISP16_32",
402 { "OPERAND_TYPE_ANYDISP",
403 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
404 { "OPERAND_TYPE_IMM16_32",
406 { "OPERAND_TYPE_IMM16_32S",
408 { "OPERAND_TYPE_IMM16_32_32S",
409 "Imm16|Imm32|Imm32S" },
410 { "OPERAND_TYPE_IMM32_64",
412 { "OPERAND_TYPE_IMM32_32S_DISP32",
413 "Imm32|Imm32S|Disp32" },
414 { "OPERAND_TYPE_IMM64_DISP64",
416 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
417 "Imm32|Imm32S|Imm64|Disp32" },
418 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
419 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
420 { "OPERAND_TYPE_VEC_IMM4",
422 { "OPERAND_TYPE_REGBND",
424 { "OPERAND_TYPE_VEC_DISP8",
428 typedef struct bitfield
435 #define BITFIELD(n) { n, 0, #n }
437 static bitfield cpu_flags[] =
445 BITFIELD (CpuClflush),
447 BITFIELD (CpuSYSCALL),
452 BITFIELD (CpuFISTTP),
458 BITFIELD (CpuSSE4_1),
459 BITFIELD (CpuSSE4_2),
462 BITFIELD (CpuAVX512F),
463 BITFIELD (CpuAVX512CD),
464 BITFIELD (CpuAVX512ER),
465 BITFIELD (CpuAVX512PF),
466 BITFIELD (CpuAVX512VL),
467 BITFIELD (CpuAVX512DQ),
468 BITFIELD (CpuAVX512BW),
474 BITFIELD (Cpu3dnowA),
475 BITFIELD (CpuPadLock),
481 BITFIELD (CpuXsaveopt),
483 BITFIELD (CpuPCLMUL),
494 BITFIELD (CpuRdtscp),
495 BITFIELD (CpuFSGSBase),
502 BITFIELD (CpuINVPCID),
503 BITFIELD (CpuVMFUNC),
504 BITFIELD (CpuRDSEED),
506 BITFIELD (CpuPRFCHW),
510 BITFIELD (CpuClflushOpt),
511 BITFIELD (CpuXSAVES),
512 BITFIELD (CpuXSAVEC),
513 BITFIELD (CpuPREFETCHWT1),
519 BITFIELD (CpuAVX512IFMA),
520 BITFIELD (CpuAVX512VBMI),
521 BITFIELD (CpuAVX512_4FMAPS),
522 BITFIELD (CpuAVX512_4VNNIW),
523 BITFIELD (CpuAVX512_VPOPCNTDQ),
524 BITFIELD (CpuMWAITX),
525 BITFIELD (CpuCLZERO),
528 BITFIELD (CpuPTWRITE),
530 BITFIELD (CpuRegMMX),
531 BITFIELD (CpuRegXMM),
532 BITFIELD (CpuRegYMM),
533 BITFIELD (CpuRegZMM),
534 BITFIELD (CpuRegMask),
536 BITFIELD (CpuUnused),
540 static bitfield opcode_modifiers[] =
546 BITFIELD (ShortForm),
548 BITFIELD (JumpDword),
550 BITFIELD (JumpInterSegment),
557 BITFIELD (CheckRegSize),
558 BITFIELD (IgnoreSize),
559 BITFIELD (DefaultSize),
568 BITFIELD (BNDPrefixOk),
569 BITFIELD (IsLockable),
570 BITFIELD (RegKludge),
571 BITFIELD (FirstXmm0),
572 BITFIELD (Implicit1stXmm0),
573 BITFIELD (RepPrefixOk),
574 BITFIELD (HLEPrefixOk),
577 BITFIELD (AddrPrefixOp0),
586 BITFIELD (VexOpcode),
587 BITFIELD (VexSources),
588 BITFIELD (VexImmExt),
595 BITFIELD (Broadcast),
596 BITFIELD (StaticRounding),
598 BITFIELD (Disp8MemShift),
599 BITFIELD (NoDefMask),
600 BITFIELD (ImplicitQuadGroup),
602 BITFIELD (ATTMnemonic),
603 BITFIELD (ATTSyntax),
604 BITFIELD (IntelSyntax),
609 static bitfield operand_types[] =
628 BITFIELD (BaseIndex),
634 BITFIELD (InOutPortReg),
635 BITFIELD (ShiftCount),
643 BITFIELD (JumpAbsolute),
656 BITFIELD (Unspecified),
660 BITFIELD (Vec_Disp8),
666 static const char *filename;
669 compare (const void *x, const void *y)
671 const bitfield *xp = (const bitfield *) x;
672 const bitfield *yp = (const bitfield *) y;
673 return xp->position - yp->position;
677 fail (const char *message, ...)
681 va_start (args, message);
682 fprintf (stderr, _("%s: Error: "), program_name);
683 vfprintf (stderr, message, args);
689 process_copyright (FILE *fp)
691 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
692 /* Copyright (C) 2007-2017 Free Software Foundation, Inc.\n\
694 This file is part of the GNU opcodes library.\n\
696 This library is free software; you can redistribute it and/or modify\n\
697 it under the terms of the GNU General Public License as published by\n\
698 the Free Software Foundation; either version 3, or (at your option)\n\
699 any later version.\n\
701 It is distributed in the hope that it will be useful, but WITHOUT\n\
702 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
703 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
704 License for more details.\n\
706 You should have received a copy of the GNU General Public License\n\
707 along with this program; if not, write to the Free Software\n\
708 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
709 MA 02110-1301, USA. */\n");
712 /* Remove leading white spaces. */
715 remove_leading_whitespaces (char *str)
717 while (ISSPACE (*str))
722 /* Remove trailing white spaces. */
725 remove_trailing_whitespaces (char *str)
727 size_t last = strlen (str);
735 if (ISSPACE (str [last]))
743 /* Find next field separated by SEP and terminate it. Return a
744 pointer to the one after it. */
747 next_field (char *str, char sep, char **next, char *last)
751 p = remove_leading_whitespaces (str);
752 for (str = p; *str != sep && *str != '\0'; str++);
755 remove_trailing_whitespaces (p);
765 static void set_bitfield (char *, bitfield *, int, unsigned int, int);
768 set_bitfield_from_cpu_flag_init (char *f, bitfield *array,
769 int value, unsigned int size,
772 char *str, *next, *last;
775 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
776 if (strcmp (cpu_flag_init[i].name, f) == 0)
778 /* Turn on selective bits. */
779 char *init = xstrdup (cpu_flag_init[i].init);
780 last = init + strlen (init);
781 for (next = init; next && next < last; )
783 str = next_field (next, '|', &next, last);
785 set_bitfield (str, array, 1, size, lineno);
795 set_bitfield (char *f, bitfield *array, int value,
796 unsigned int size, int lineno)
800 if (strcmp (f, "CpuFP") == 0)
802 set_bitfield("Cpu387", array, value, size, lineno);
803 set_bitfield("Cpu287", array, value, size, lineno);
806 else if (strcmp (f, "Mmword") == 0)
808 else if (strcmp (f, "Oword") == 0)
811 for (i = 0; i < size; i++)
812 if (strcasecmp (array[i].name, f) == 0)
814 array[i].value = value;
820 const char *v = strchr (f, '=');
827 for (i = 0; i < size; i++)
828 if (strncasecmp (array[i].name, f, n) == 0)
830 value = strtol (v + 1, &end, 0);
833 array[i].value = value;
841 /* Handle CPU_XXX_FLAGS. */
842 if (!set_bitfield_from_cpu_flag_init (f, array, value, size, lineno))
846 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
848 fail (_("Unknown bitfield: %s\n"), f);
852 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
853 int macro, const char *comma, const char *indent)
857 fprintf (table, "%s{ { ", indent);
859 for (i = 0; i < size - 1; i++)
861 if (((i + 1) % 20) != 0)
862 fprintf (table, "%d, ", flags[i].value);
864 fprintf (table, "%d,", flags[i].value);
865 if (((i + 1) % 20) == 0)
867 /* We need \\ for macro. */
869 fprintf (table, " \\\n %s", indent);
871 fprintf (table, "\n %s", indent);
875 fprintf (table, "%d } }%s\n", flags[i].value, comma);
879 process_i386_cpu_flag (FILE *table, char *flag, int macro,
880 const char *comma, const char *indent,
883 char *str, *next, *last;
885 bitfield flags [ARRAY_SIZE (cpu_flags)];
887 /* Copy the default cpu flags. */
888 memcpy (flags, cpu_flags, sizeof (cpu_flags));
890 if (strcasecmp (flag, "unknown") == 0)
892 /* We turn on everything except for cpu64 in case of
893 CPU_UNKNOWN_FLAGS. */
894 for (i = 0; i < ARRAY_SIZE (flags); i++)
895 if (flags[i].position != Cpu64)
898 else if (flag[0] == '~')
900 last = flag + strlen (flag);
907 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
914 /* First we turn on everything except for cpu64. */
915 for (i = 0; i < ARRAY_SIZE (flags); i++)
916 if (flags[i].position != Cpu64)
919 /* Turn off selective bits. */
920 for (; next && next < last; )
922 str = next_field (next, '|', &next, last);
924 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
927 else if (strcmp (flag, "0"))
929 /* Turn on selective bits. */
930 last = flag + strlen (flag);
931 for (next = flag; next && next < last; )
933 str = next_field (next, '|', &next, last);
935 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
939 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
944 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
948 fprintf (table, " { ");
950 for (i = 0; i < size - 1; i++)
952 if (((i + 1) % 20) != 0)
953 fprintf (table, "%d, ", modifier[i].value);
955 fprintf (table, "%d,", modifier[i].value);
956 if (((i + 1) % 20) == 0)
957 fprintf (table, "\n ");
960 fprintf (table, "%d },\n", modifier[i].value);
964 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
966 char *str, *next, *last;
967 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
969 /* Copy the default opcode modifier. */
970 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
972 if (strcmp (mod, "0"))
974 last = mod + strlen (mod);
975 for (next = mod; next && next < last; )
977 str = next_field (next, '|', &next, last);
979 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
983 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
987 output_operand_type (FILE *table, bitfield *types, unsigned int size,
988 int macro, const char *indent)
992 fprintf (table, "{ { ");
994 for (i = 0; i < size - 1; i++)
996 if (((i + 1) % 20) != 0)
997 fprintf (table, "%d, ", types[i].value);
999 fprintf (table, "%d,", types[i].value);
1000 if (((i + 1) % 20) == 0)
1002 /* We need \\ for macro. */
1004 fprintf (table, " \\\n%s", indent);
1006 fprintf (table, "\n%s", indent);
1010 fprintf (table, "%d } }", types[i].value);
1014 process_i386_operand_type (FILE *table, char *op, int macro,
1015 const char *indent, int lineno)
1017 char *str, *next, *last;
1018 bitfield types [ARRAY_SIZE (operand_types)];
1020 /* Copy the default operand type. */
1021 memcpy (types, operand_types, sizeof (types));
1023 if (strcmp (op, "0"))
1025 last = op + strlen (op);
1026 for (next = op; next && next < last; )
1028 str = next_field (next, '|', &next, last);
1030 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1033 output_operand_type (table, types, ARRAY_SIZE (types), macro,
1038 output_i386_opcode (FILE *table, const char *name, char *str,
1039 char *last, int lineno)
1042 char *operands, *base_opcode, *extension_opcode, *opcode_length;
1043 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1045 /* Find number of operands. */
1046 operands = next_field (str, ',', &str, last);
1048 /* Find base_opcode. */
1049 base_opcode = next_field (str, ',', &str, last);
1051 /* Find extension_opcode. */
1052 extension_opcode = next_field (str, ',', &str, last);
1054 /* Find opcode_length. */
1055 opcode_length = next_field (str, ',', &str, last);
1057 /* Find cpu_flags. */
1058 cpu_flags = next_field (str, ',', &str, last);
1060 /* Find opcode_modifier. */
1061 opcode_modifier = next_field (str, ',', &str, last);
1063 /* Remove the first {. */
1064 str = remove_leading_whitespaces (str);
1067 str = remove_leading_whitespaces (str + 1);
1071 /* There are at least "X}". */
1075 /* Remove trailing white spaces and }. */
1079 if (ISSPACE (str[i]) || str[i] == '}')
1088 /* Find operand_types. */
1089 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1093 operand_types [i] = NULL;
1097 operand_types [i] = next_field (str, ',', &str, last);
1098 if (*operand_types[i] == '0')
1101 operand_types[i] = NULL;
1106 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
1107 name, operands, base_opcode, extension_opcode,
1110 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
1112 process_i386_opcode_modifier (table, opcode_modifier, lineno);
1114 fprintf (table, " { ");
1116 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1118 if (operand_types[i] == NULL || *operand_types[i] == '0')
1121 process_i386_operand_type (table, "0", 0, "\t ", lineno);
1126 fprintf (table, ",\n ");
1128 process_i386_operand_type (table, operand_types[i], 0,
1131 fprintf (table, " } },\n");
1134 struct opcode_hash_entry
1136 struct opcode_hash_entry *next;
1142 /* Calculate the hash value of an opcode hash entry P. */
1145 opcode_hash_hash (const void *p)
1147 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1148 return htab_hash_string (entry->name);
1151 /* Compare a string Q against an opcode hash entry P. */
1154 opcode_hash_eq (const void *p, const void *q)
1156 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1157 const char *name = (const char *) q;
1158 return strcmp (name, entry->name) == 0;
1162 process_i386_opcodes (FILE *table)
1167 char *str, *p, *last, *name;
1168 struct opcode_hash_entry **hash_slot, **entry, *next;
1169 htab_t opcode_hash_table;
1170 struct opcode_hash_entry **opcode_array;
1171 unsigned int opcode_array_size = 1024;
1174 filename = "i386-opc.tbl";
1175 fp = fopen (filename, "r");
1178 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1182 opcode_array = (struct opcode_hash_entry **)
1183 xmalloc (sizeof (*opcode_array) * opcode_array_size);
1185 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1186 opcode_hash_eq, NULL,
1189 fprintf (table, "\n/* i386 opcode table. */\n\n");
1190 fprintf (table, "const insn_template i386_optab[] =\n{\n");
1192 /* Put everything on opcode array. */
1195 if (fgets (buf, sizeof (buf), fp) == NULL)
1200 p = remove_leading_whitespaces (buf);
1202 /* Skip comments. */
1203 str = strstr (p, "//");
1207 /* Remove trailing white spaces. */
1208 remove_trailing_whitespaces (p);
1213 /* Ignore comments. */
1221 last = p + strlen (p);
1224 name = next_field (p, ',', &str, last);
1226 /* Get the slot in hash table. */
1227 hash_slot = (struct opcode_hash_entry **)
1228 htab_find_slot_with_hash (opcode_hash_table, name,
1229 htab_hash_string (name),
1232 if (*hash_slot == NULL)
1234 /* It is the new one. Put it on opcode array. */
1235 if (i >= opcode_array_size)
1237 /* Grow the opcode array when needed. */
1238 opcode_array_size += 1024;
1239 opcode_array = (struct opcode_hash_entry **)
1240 xrealloc (opcode_array,
1241 sizeof (*opcode_array) * opcode_array_size);
1244 opcode_array[i] = (struct opcode_hash_entry *)
1245 xmalloc (sizeof (struct opcode_hash_entry));
1246 opcode_array[i]->next = NULL;
1247 opcode_array[i]->name = xstrdup (name);
1248 opcode_array[i]->opcode = xstrdup (str);
1249 opcode_array[i]->lineno = lineno;
1250 *hash_slot = opcode_array[i];
1255 /* Append it to the existing one. */
1257 while ((*entry) != NULL)
1258 entry = &(*entry)->next;
1259 *entry = (struct opcode_hash_entry *)
1260 xmalloc (sizeof (struct opcode_hash_entry));
1261 (*entry)->next = NULL;
1262 (*entry)->name = (*hash_slot)->name;
1263 (*entry)->opcode = xstrdup (str);
1264 (*entry)->lineno = lineno;
1268 /* Process opcode array. */
1269 for (j = 0; j < i; j++)
1271 for (next = opcode_array[j]; next; next = next->next)
1275 lineno = next->lineno;
1276 last = str + strlen (str);
1277 output_i386_opcode (table, name, str, last, lineno);
1283 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1285 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1287 process_i386_opcode_modifier (table, "0", -1);
1289 fprintf (table, " { ");
1290 process_i386_operand_type (table, "0", 0, "\t ", -1);
1291 fprintf (table, " } }\n");
1293 fprintf (table, "};\n");
1297 process_i386_registers (FILE *table)
1301 char *str, *p, *last;
1302 char *reg_name, *reg_type, *reg_flags, *reg_num;
1303 char *dw2_32_num, *dw2_64_num;
1306 filename = "i386-reg.tbl";
1307 fp = fopen (filename, "r");
1309 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1312 fprintf (table, "\n/* i386 register table. */\n\n");
1313 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1317 if (fgets (buf, sizeof (buf), fp) == NULL)
1322 p = remove_leading_whitespaces (buf);
1324 /* Skip comments. */
1325 str = strstr (p, "//");
1329 /* Remove trailing white spaces. */
1330 remove_trailing_whitespaces (p);
1335 fprintf (table, "%s\n", p);
1343 last = p + strlen (p);
1345 /* Find reg_name. */
1346 reg_name = next_field (p, ',', &str, last);
1348 /* Find reg_type. */
1349 reg_type = next_field (str, ',', &str, last);
1351 /* Find reg_flags. */
1352 reg_flags = next_field (str, ',', &str, last);
1355 reg_num = next_field (str, ',', &str, last);
1357 fprintf (table, " { \"%s\",\n ", reg_name);
1359 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1361 /* Find 32-bit Dwarf2 register number. */
1362 dw2_32_num = next_field (str, ',', &str, last);
1364 /* Find 64-bit Dwarf2 register number. */
1365 dw2_64_num = next_field (str, ',', &str, last);
1367 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1368 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1373 fprintf (table, "};\n");
1375 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1379 process_i386_initializers (void)
1382 FILE *fp = fopen ("i386-init.h", "w");
1386 fail (_("can't create i386-init.h, errno = %s\n"),
1389 process_copyright (fp);
1391 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1393 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1394 init = xstrdup (cpu_flag_init[i].init);
1395 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1399 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1401 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1402 init = xstrdup (operand_type_init[i].init);
1403 process_i386_operand_type (fp, init, 1, " ", -1);
1411 /* Program options. */
1412 #define OPTION_SRCDIR 200
1414 struct option long_options[] =
1416 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1417 {"debug", no_argument, NULL, 'd'},
1418 {"version", no_argument, NULL, 'V'},
1419 {"help", no_argument, NULL, 'h'},
1420 {0, no_argument, NULL, 0}
1424 print_version (void)
1426 printf ("%s: version 1.0\n", program_name);
1431 usage (FILE * stream, int status)
1433 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1439 main (int argc, char **argv)
1441 extern int chdir (char *);
1442 char *srcdir = NULL;
1444 unsigned int i, cpumax;
1447 program_name = *argv;
1448 xmalloc_set_program_name (program_name);
1450 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1475 if (chdir (srcdir) != 0)
1476 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1477 srcdir, xstrerror (errno));
1479 /* cpu_flags isn't sorted by position. */
1481 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
1482 if (cpu_flags[i].position > cpumax)
1483 cpumax = cpu_flags[i].position;
1485 /* Check the unused bitfield in i386_cpu_flags. */
1487 if ((cpumax - 1) != CpuMax)
1488 fail (_("CpuMax != %d!\n"), cpumax);
1490 if (cpumax != CpuMax)
1491 fail (_("CpuMax != %d!\n"), cpumax);
1493 c = CpuNumOfBits - CpuMax - 1;
1495 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1498 /* Check the unused bitfield in i386_operand_type. */
1500 c = OTNumOfBits - OTMax - 1;
1502 fail (_("%d unused bits in i386_operand_type.\n"), c);
1505 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1508 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1509 sizeof (opcode_modifiers [0]), compare);
1511 qsort (operand_types, ARRAY_SIZE (operand_types),
1512 sizeof (operand_types [0]), compare);
1514 table = fopen ("i386-tbl.h", "w");
1516 fail (_("can't create i386-tbl.h, errno = %s\n"),
1519 process_copyright (table);
1521 process_i386_opcodes (table);
1522 process_i386_registers (table);
1523 process_i386_initializers ();