1 /* Copyright (C) 2007-2018 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" },
226 { "CPU_AVX512_VBMI2_FLAGS",
227 "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
228 { "CPU_AVX512_VNNI_FLAGS",
229 "CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
230 { "CPU_AVX512_BITALG_FLAGS",
231 "CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
237 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
240 { "CPU_RDSEED_FLAGS",
242 { "CPU_PRFCHW_FLAGS",
249 "CPU_SSE2_FLAGS|CpuSHA" },
250 { "CPU_CLFLUSHOPT_FLAGS",
252 { "CPU_XSAVES_FLAGS",
253 "CPU_XSAVE_FLAGS|CpuXSAVES" },
254 { "CPU_XSAVEC_FLAGS",
255 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
256 { "CPU_PREFETCHWT1_FLAGS",
262 { "CPU_CLZERO_FLAGS",
264 { "CPU_MWAITX_FLAGS",
270 { "CPU_PTWRITE_FLAGS",
280 { "CPU_VPCLMULQDQ_FLAGS",
282 { "CPU_WBNOINVD_FLAGS",
284 { "CPU_PCONFIG_FLAGS",
286 { "CPU_WAITPKG_FLAGS",
288 { "CPU_CLDEMOTE_FLAGS",
290 { "CPU_ANY_X87_FLAGS",
291 "CPU_ANY_287_FLAGS|Cpu8087" },
292 { "CPU_ANY_287_FLAGS",
293 "CPU_ANY_387_FLAGS|Cpu287" },
294 { "CPU_ANY_387_FLAGS",
295 "CPU_ANY_687_FLAGS|Cpu387" },
296 { "CPU_ANY_687_FLAGS",
297 "Cpu687|CpuFISTTP" },
298 { "CPU_ANY_MMX_FLAGS",
299 "CPU_3DNOWA_FLAGS" },
300 { "CPU_ANY_SSE_FLAGS",
301 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
302 { "CPU_ANY_SSE2_FLAGS",
303 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
304 { "CPU_ANY_SSE3_FLAGS",
305 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
306 { "CPU_ANY_SSSE3_FLAGS",
307 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
308 { "CPU_ANY_SSE4_1_FLAGS",
309 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
310 { "CPU_ANY_SSE4_2_FLAGS",
312 { "CPU_ANY_AVX_FLAGS",
313 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
314 { "CPU_ANY_AVX2_FLAGS",
316 { "CPU_ANY_AVX512F_FLAGS",
317 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512F" },
318 { "CPU_ANY_AVX512CD_FLAGS",
320 { "CPU_ANY_AVX512ER_FLAGS",
322 { "CPU_ANY_AVX512PF_FLAGS",
324 { "CPU_ANY_AVX512DQ_FLAGS",
326 { "CPU_ANY_AVX512BW_FLAGS",
328 { "CPU_ANY_AVX512VL_FLAGS",
330 { "CPU_ANY_AVX512IFMA_FLAGS",
332 { "CPU_ANY_AVX512VBMI_FLAGS",
334 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
335 "CpuAVX512_4FMAPS" },
336 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
337 "CpuAVX512_4VNNIW" },
338 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
339 "CpuAVX512_VPOPCNTDQ" },
340 { "CPU_ANY_IBT_FLAGS",
342 { "CPU_ANY_SHSTK_FLAGS",
344 { "CPU_ANY_AVX512_VBMI2_FLAGS",
346 { "CPU_ANY_AVX512_VNNI_FLAGS",
348 { "CPU_ANY_AVX512_BITALG_FLAGS",
349 "CpuAVX512_BITALG" },
352 static const initializer operand_type_shorthands[] =
354 { "Reg8", "Reg|Byte" },
355 { "Reg16", "Reg|Word" },
356 { "Reg32", "Reg|Dword" },
357 { "Reg64", "Reg|Qword" },
358 { "FloatAcc", "Acc|Tbyte" },
359 { "FloatReg", "Reg|Tbyte" },
360 { "RegXMM", "RegSIMD|Xmmword" },
361 { "RegYMM", "RegSIMD|Ymmword" },
362 { "RegZMM", "RegSIMD|Zmmword" },
365 static initializer operand_type_init[] =
367 { "OPERAND_TYPE_NONE",
369 { "OPERAND_TYPE_REG8",
371 { "OPERAND_TYPE_REG16",
373 { "OPERAND_TYPE_REG32",
375 { "OPERAND_TYPE_REG64",
377 { "OPERAND_TYPE_IMM1",
379 { "OPERAND_TYPE_IMM8",
381 { "OPERAND_TYPE_IMM8S",
383 { "OPERAND_TYPE_IMM16",
385 { "OPERAND_TYPE_IMM32",
387 { "OPERAND_TYPE_IMM32S",
389 { "OPERAND_TYPE_IMM64",
391 { "OPERAND_TYPE_BASEINDEX",
393 { "OPERAND_TYPE_DISP8",
395 { "OPERAND_TYPE_DISP16",
397 { "OPERAND_TYPE_DISP32",
399 { "OPERAND_TYPE_DISP32S",
401 { "OPERAND_TYPE_DISP64",
403 { "OPERAND_TYPE_INOUTPORTREG",
405 { "OPERAND_TYPE_SHIFTCOUNT",
407 { "OPERAND_TYPE_CONTROL",
409 { "OPERAND_TYPE_TEST",
411 { "OPERAND_TYPE_DEBUG",
413 { "OPERAND_TYPE_FLOATREG",
415 { "OPERAND_TYPE_FLOATACC",
417 { "OPERAND_TYPE_SREG2",
419 { "OPERAND_TYPE_SREG3",
421 { "OPERAND_TYPE_ACC",
423 { "OPERAND_TYPE_JUMPABSOLUTE",
425 { "OPERAND_TYPE_REGMMX",
427 { "OPERAND_TYPE_REGXMM",
429 { "OPERAND_TYPE_REGYMM",
431 { "OPERAND_TYPE_REGZMM",
433 { "OPERAND_TYPE_REGMASK",
435 { "OPERAND_TYPE_ESSEG",
437 { "OPERAND_TYPE_ACC32",
439 { "OPERAND_TYPE_ACC64",
441 { "OPERAND_TYPE_INOUTPORTREG",
443 { "OPERAND_TYPE_REG16_INOUTPORTREG",
444 "Reg16|InOutPortReg" },
445 { "OPERAND_TYPE_DISP16_32",
447 { "OPERAND_TYPE_ANYDISP",
448 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
449 { "OPERAND_TYPE_IMM16_32",
451 { "OPERAND_TYPE_IMM16_32S",
453 { "OPERAND_TYPE_IMM16_32_32S",
454 "Imm16|Imm32|Imm32S" },
455 { "OPERAND_TYPE_IMM32_64",
457 { "OPERAND_TYPE_IMM32_32S_DISP32",
458 "Imm32|Imm32S|Disp32" },
459 { "OPERAND_TYPE_IMM64_DISP64",
461 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
462 "Imm32|Imm32S|Imm64|Disp32" },
463 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
464 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
465 { "OPERAND_TYPE_VEC_IMM4",
467 { "OPERAND_TYPE_REGBND",
471 typedef struct bitfield
478 #define BITFIELD(n) { n, 0, #n }
480 static bitfield cpu_flags[] =
488 BITFIELD (CpuClflush),
490 BITFIELD (CpuSYSCALL),
495 BITFIELD (CpuFISTTP),
501 BITFIELD (CpuSSE4_1),
502 BITFIELD (CpuSSE4_2),
505 BITFIELD (CpuAVX512F),
506 BITFIELD (CpuAVX512CD),
507 BITFIELD (CpuAVX512ER),
508 BITFIELD (CpuAVX512PF),
509 BITFIELD (CpuAVX512VL),
510 BITFIELD (CpuAVX512DQ),
511 BITFIELD (CpuAVX512BW),
517 BITFIELD (Cpu3dnowA),
518 BITFIELD (CpuPadLock),
524 BITFIELD (CpuXsaveopt),
526 BITFIELD (CpuPCLMUL),
537 BITFIELD (CpuRdtscp),
538 BITFIELD (CpuFSGSBase),
545 BITFIELD (CpuINVPCID),
546 BITFIELD (CpuVMFUNC),
547 BITFIELD (CpuRDSEED),
549 BITFIELD (CpuPRFCHW),
553 BITFIELD (CpuClflushOpt),
554 BITFIELD (CpuXSAVES),
555 BITFIELD (CpuXSAVEC),
556 BITFIELD (CpuPREFETCHWT1),
562 BITFIELD (CpuAVX512IFMA),
563 BITFIELD (CpuAVX512VBMI),
564 BITFIELD (CpuAVX512_4FMAPS),
565 BITFIELD (CpuAVX512_4VNNIW),
566 BITFIELD (CpuAVX512_VPOPCNTDQ),
567 BITFIELD (CpuAVX512_VBMI2),
568 BITFIELD (CpuAVX512_VNNI),
569 BITFIELD (CpuAVX512_BITALG),
570 BITFIELD (CpuMWAITX),
571 BITFIELD (CpuCLZERO),
574 BITFIELD (CpuPTWRITE),
579 BITFIELD (CpuVPCLMULQDQ),
580 BITFIELD (CpuWBNOINVD),
581 BITFIELD (CpuPCONFIG),
582 BITFIELD (CpuWAITPKG),
583 BITFIELD (CpuCLDEMOTE),
584 BITFIELD (CpuRegMMX),
585 BITFIELD (CpuRegXMM),
586 BITFIELD (CpuRegYMM),
587 BITFIELD (CpuRegZMM),
588 BITFIELD (CpuRegMask),
590 BITFIELD (CpuUnused),
594 static bitfield opcode_modifiers[] =
600 BITFIELD (ShortForm),
602 BITFIELD (JumpDword),
604 BITFIELD (JumpInterSegment),
610 BITFIELD (CheckRegSize),
611 BITFIELD (IgnoreSize),
612 BITFIELD (DefaultSize),
621 BITFIELD (BNDPrefixOk),
622 BITFIELD (NoTrackPrefixOk),
623 BITFIELD (IsLockable),
624 BITFIELD (RegKludge),
625 BITFIELD (Implicit1stXmm0),
626 BITFIELD (RepPrefixOk),
627 BITFIELD (HLEPrefixOk),
630 BITFIELD (AddrPrefixOp0),
639 BITFIELD (VexOpcode),
640 BITFIELD (VexSources),
641 BITFIELD (VexImmExt),
647 BITFIELD (Broadcast),
648 BITFIELD (StaticRounding),
650 BITFIELD (Disp8MemShift),
651 BITFIELD (NoDefMask),
652 BITFIELD (ImplicitQuadGroup),
654 BITFIELD (ATTMnemonic),
655 BITFIELD (ATTSyntax),
656 BITFIELD (IntelSyntax),
661 static bitfield operand_types[] =
674 BITFIELD (BaseIndex),
680 BITFIELD (InOutPortReg),
681 BITFIELD (ShiftCount),
688 BITFIELD (JumpAbsolute),
701 BITFIELD (Unspecified),
710 static const char *filename;
711 static i386_cpu_flags active_cpu_flags;
712 static int active_isstring;
715 compare (const void *x, const void *y)
717 const bitfield *xp = (const bitfield *) x;
718 const bitfield *yp = (const bitfield *) y;
719 return xp->position - yp->position;
723 fail (const char *message, ...)
727 va_start (args, message);
728 fprintf (stderr, _("%s: error: "), program_name);
729 vfprintf (stderr, message, args);
735 process_copyright (FILE *fp)
737 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
738 /* Copyright (C) 2007-2018 Free Software Foundation, Inc.\n\
740 This file is part of the GNU opcodes library.\n\
742 This library is free software; you can redistribute it and/or modify\n\
743 it under the terms of the GNU General Public License as published by\n\
744 the Free Software Foundation; either version 3, or (at your option)\n\
745 any later version.\n\
747 It is distributed in the hope that it will be useful, but WITHOUT\n\
748 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
749 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
750 License for more details.\n\
752 You should have received a copy of the GNU General Public License\n\
753 along with this program; if not, write to the Free Software\n\
754 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
755 MA 02110-1301, USA. */\n");
758 /* Remove leading white spaces. */
761 remove_leading_whitespaces (char *str)
763 while (ISSPACE (*str))
768 /* Remove trailing white spaces. */
771 remove_trailing_whitespaces (char *str)
773 size_t last = strlen (str);
781 if (ISSPACE (str [last]))
789 /* Find next field separated by SEP and terminate it. Return a
790 pointer to the one after it. */
793 next_field (char *str, char sep, char **next, char *last)
797 p = remove_leading_whitespaces (str);
798 for (str = p; *str != sep && *str != '\0'; str++);
801 remove_trailing_whitespaces (p);
811 static void set_bitfield (char *, bitfield *, int, unsigned int, int);
814 set_bitfield_from_shorthand (char *f, bitfield *array, unsigned int size,
817 char *str, *next, *last;
820 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
821 if (strcmp (cpu_flag_init[i].name, f) == 0)
823 /* Turn on selective bits. */
824 char *init = xstrdup (cpu_flag_init[i].init);
825 last = init + strlen (init);
826 for (next = init; next && next < last; )
828 str = next_field (next, '|', &next, last);
830 set_bitfield (str, array, 1, size, lineno);
836 for (i = 0; i < ARRAY_SIZE (operand_type_shorthands); i++)
837 if (strcmp (operand_type_shorthands[i].name, f) == 0)
839 /* Turn on selective bits. */
840 char *init = xstrdup (operand_type_shorthands[i].init);
841 last = init + strlen (init);
842 for (next = init; next && next < last; )
844 str = next_field (next, '|', &next, last);
846 set_bitfield (str, array, 1, size, lineno);
856 set_bitfield (char *f, bitfield *array, int value,
857 unsigned int size, int lineno)
861 if (strcmp (f, "CpuFP") == 0)
863 set_bitfield("Cpu387", array, value, size, lineno);
864 set_bitfield("Cpu287", array, value, size, lineno);
867 else if (strcmp (f, "Mmword") == 0)
869 else if (strcmp (f, "Oword") == 0)
872 for (i = 0; i < size; i++)
873 if (strcasecmp (array[i].name, f) == 0)
875 array[i].value = value;
881 const char *v = strchr (f, '=');
888 for (i = 0; i < size; i++)
889 if (strncasecmp (array[i].name, f, n) == 0)
891 value = strtol (v + 1, &end, 0);
894 array[i].value = value;
902 /* Handle shorthands. */
903 if (value == 1 && !set_bitfield_from_shorthand (f, array, size, lineno))
907 fail (_("%s: %d: unknown bitfield: %s\n"), filename, lineno, f);
909 fail (_("unknown bitfield: %s\n"), f);
913 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
914 int macro, const char *comma, const char *indent)
918 memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
920 fprintf (table, "%s{ { ", indent);
922 for (i = 0; i < size - 1; i++)
924 if (((i + 1) % 20) != 0)
925 fprintf (table, "%d, ", flags[i].value);
927 fprintf (table, "%d,", flags[i].value);
928 if (((i + 1) % 20) == 0)
930 /* We need \\ for macro. */
932 fprintf (table, " \\\n %s", indent);
934 fprintf (table, "\n %s", indent);
937 active_cpu_flags.array[i / 32] |= 1U << (i % 32);
940 fprintf (table, "%d } }%s\n", flags[i].value, comma);
944 process_i386_cpu_flag (FILE *table, char *flag, int macro,
945 const char *comma, const char *indent,
948 char *str, *next, *last;
950 bitfield flags [ARRAY_SIZE (cpu_flags)];
952 /* Copy the default cpu flags. */
953 memcpy (flags, cpu_flags, sizeof (cpu_flags));
955 if (strcasecmp (flag, "unknown") == 0)
957 /* We turn on everything except for cpu64 in case of
958 CPU_UNKNOWN_FLAGS. */
959 for (i = 0; i < ARRAY_SIZE (flags); i++)
960 if (flags[i].position != Cpu64)
963 else if (flag[0] == '~')
965 last = flag + strlen (flag);
972 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename,
979 /* First we turn on everything except for cpu64. */
980 for (i = 0; i < ARRAY_SIZE (flags); i++)
981 if (flags[i].position != Cpu64)
984 /* Turn off selective bits. */
985 for (; next && next < last; )
987 str = next_field (next, '|', &next, last);
989 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
992 else if (strcmp (flag, "0"))
994 /* Turn on selective bits. */
995 last = flag + strlen (flag);
996 for (next = flag; next && next < last; )
998 str = next_field (next, '|', &next, last);
1000 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
1004 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
1009 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
1013 fprintf (table, " { ");
1015 for (i = 0; i < size - 1; i++)
1017 if (((i + 1) % 20) != 0)
1018 fprintf (table, "%d, ", modifier[i].value);
1020 fprintf (table, "%d,", modifier[i].value);
1021 if (((i + 1) % 20) == 0)
1022 fprintf (table, "\n ");
1025 fprintf (table, "%d },\n", modifier[i].value);
1029 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
1031 char *str, *next, *last;
1032 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
1034 active_isstring = 0;
1036 /* Copy the default opcode modifier. */
1037 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
1039 if (strcmp (mod, "0"))
1041 last = mod + strlen (mod);
1042 for (next = mod; next && next < last; )
1044 str = next_field (next, '|', &next, last);
1047 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
1049 if (strcasecmp(str, "IsString") == 0)
1050 active_isstring = 1;
1054 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
1064 output_operand_type (FILE *table, bitfield *types, unsigned int size,
1065 enum stage stage, const char *indent)
1069 fprintf (table, "{ { ");
1071 for (i = 0; i < size - 1; i++)
1073 if (((i + 1) % 20) != 0)
1074 fprintf (table, "%d, ", types[i].value);
1076 fprintf (table, "%d,", types[i].value);
1077 if (((i + 1) % 20) == 0)
1079 /* We need \\ for macro. */
1080 if (stage == stage_macros)
1081 fprintf (table, " \\\n%s", indent);
1083 fprintf (table, "\n%s", indent);
1087 fprintf (table, "%d } }", types[i].value);
1091 process_i386_operand_type (FILE *table, char *op, enum stage stage,
1092 const char *indent, int lineno)
1094 char *str, *next, *last;
1095 bitfield types [ARRAY_SIZE (operand_types)];
1097 /* Copy the default operand type. */
1098 memcpy (types, operand_types, sizeof (types));
1100 if (strcmp (op, "0"))
1104 last = op + strlen (op);
1105 for (next = op; next && next < last; )
1107 str = next_field (next, '|', &next, last);
1110 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1111 if (strcasecmp(str, "BaseIndex") == 0)
1116 if (stage == stage_opcodes && baseindex && !active_isstring)
1118 set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno);
1119 if (!active_cpu_flags.bitfield.cpu64
1120 && !active_cpu_flags.bitfield.cpumpx)
1121 set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
1122 set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
1123 if (!active_cpu_flags.bitfield.cpuno64)
1124 set_bitfield("Disp32S", types, 1, ARRAY_SIZE (types), lineno);
1127 output_operand_type (table, types, ARRAY_SIZE (types), stage,
1132 output_i386_opcode (FILE *table, const char *name, char *str,
1133 char *last, int lineno)
1136 char *operands, *base_opcode, *extension_opcode, *opcode_length;
1137 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1139 /* Find number of operands. */
1140 operands = next_field (str, ',', &str, last);
1142 /* Find base_opcode. */
1143 base_opcode = next_field (str, ',', &str, last);
1145 /* Find extension_opcode. */
1146 extension_opcode = next_field (str, ',', &str, last);
1148 /* Find opcode_length. */
1149 opcode_length = next_field (str, ',', &str, last);
1151 /* Find cpu_flags. */
1152 cpu_flags = next_field (str, ',', &str, last);
1154 /* Find opcode_modifier. */
1155 opcode_modifier = next_field (str, ',', &str, last);
1157 /* Remove the first {. */
1158 str = remove_leading_whitespaces (str);
1161 str = remove_leading_whitespaces (str + 1);
1165 /* There are at least "X}". */
1169 /* Remove trailing white spaces and }. */
1173 if (ISSPACE (str[i]) || str[i] == '}')
1182 /* Find operand_types. */
1183 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1187 operand_types [i] = NULL;
1191 operand_types [i] = next_field (str, ',', &str, last);
1192 if (*operand_types[i] == '0')
1195 operand_types[i] = NULL;
1200 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
1201 name, operands, base_opcode, extension_opcode,
1204 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
1206 process_i386_opcode_modifier (table, opcode_modifier, lineno);
1208 fprintf (table, " { ");
1210 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1212 if (operand_types[i] == NULL || *operand_types[i] == '0')
1215 process_i386_operand_type (table, "0", stage_opcodes, "\t ",
1221 fprintf (table, ",\n ");
1223 process_i386_operand_type (table, operand_types[i], stage_opcodes,
1226 fprintf (table, " } },\n");
1229 struct opcode_hash_entry
1231 struct opcode_hash_entry *next;
1237 /* Calculate the hash value of an opcode hash entry P. */
1240 opcode_hash_hash (const void *p)
1242 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1243 return htab_hash_string (entry->name);
1246 /* Compare a string Q against an opcode hash entry P. */
1249 opcode_hash_eq (const void *p, const void *q)
1251 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1252 const char *name = (const char *) q;
1253 return strcmp (name, entry->name) == 0;
1257 process_i386_opcodes (FILE *table)
1262 char *str, *p, *last, *name;
1263 struct opcode_hash_entry **hash_slot, **entry, *next;
1264 htab_t opcode_hash_table;
1265 struct opcode_hash_entry **opcode_array;
1266 unsigned int opcode_array_size = 1024;
1269 filename = "i386-opc.tbl";
1270 fp = fopen (filename, "r");
1273 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1277 opcode_array = (struct opcode_hash_entry **)
1278 xmalloc (sizeof (*opcode_array) * opcode_array_size);
1280 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1281 opcode_hash_eq, NULL,
1284 fprintf (table, "\n/* i386 opcode table. */\n\n");
1285 fprintf (table, "const insn_template i386_optab[] =\n{\n");
1287 /* Put everything on opcode array. */
1290 if (fgets (buf, sizeof (buf), fp) == NULL)
1295 p = remove_leading_whitespaces (buf);
1297 /* Skip comments. */
1298 str = strstr (p, "//");
1302 /* Remove trailing white spaces. */
1303 remove_trailing_whitespaces (p);
1308 /* Ignore comments. */
1316 last = p + strlen (p);
1319 name = next_field (p, ',', &str, last);
1321 /* Get the slot in hash table. */
1322 hash_slot = (struct opcode_hash_entry **)
1323 htab_find_slot_with_hash (opcode_hash_table, name,
1324 htab_hash_string (name),
1327 if (*hash_slot == NULL)
1329 /* It is the new one. Put it on opcode array. */
1330 if (i >= opcode_array_size)
1332 /* Grow the opcode array when needed. */
1333 opcode_array_size += 1024;
1334 opcode_array = (struct opcode_hash_entry **)
1335 xrealloc (opcode_array,
1336 sizeof (*opcode_array) * opcode_array_size);
1339 opcode_array[i] = (struct opcode_hash_entry *)
1340 xmalloc (sizeof (struct opcode_hash_entry));
1341 opcode_array[i]->next = NULL;
1342 opcode_array[i]->name = xstrdup (name);
1343 opcode_array[i]->opcode = xstrdup (str);
1344 opcode_array[i]->lineno = lineno;
1345 *hash_slot = opcode_array[i];
1350 /* Append it to the existing one. */
1352 while ((*entry) != NULL)
1353 entry = &(*entry)->next;
1354 *entry = (struct opcode_hash_entry *)
1355 xmalloc (sizeof (struct opcode_hash_entry));
1356 (*entry)->next = NULL;
1357 (*entry)->name = (*hash_slot)->name;
1358 (*entry)->opcode = xstrdup (str);
1359 (*entry)->lineno = lineno;
1363 /* Process opcode array. */
1364 for (j = 0; j < i; j++)
1366 for (next = opcode_array[j]; next; next = next->next)
1370 lineno = next->lineno;
1371 last = str + strlen (str);
1372 output_i386_opcode (table, name, str, last, lineno);
1378 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1380 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1382 process_i386_opcode_modifier (table, "0", -1);
1384 fprintf (table, " { ");
1385 process_i386_operand_type (table, "0", stage_opcodes, "\t ", -1);
1386 fprintf (table, " } }\n");
1388 fprintf (table, "};\n");
1392 process_i386_registers (FILE *table)
1396 char *str, *p, *last;
1397 char *reg_name, *reg_type, *reg_flags, *reg_num;
1398 char *dw2_32_num, *dw2_64_num;
1401 filename = "i386-reg.tbl";
1402 fp = fopen (filename, "r");
1404 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1407 fprintf (table, "\n/* i386 register table. */\n\n");
1408 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1412 if (fgets (buf, sizeof (buf), fp) == NULL)
1417 p = remove_leading_whitespaces (buf);
1419 /* Skip comments. */
1420 str = strstr (p, "//");
1424 /* Remove trailing white spaces. */
1425 remove_trailing_whitespaces (p);
1430 fprintf (table, "%s\n", p);
1438 last = p + strlen (p);
1440 /* Find reg_name. */
1441 reg_name = next_field (p, ',', &str, last);
1443 /* Find reg_type. */
1444 reg_type = next_field (str, ',', &str, last);
1446 /* Find reg_flags. */
1447 reg_flags = next_field (str, ',', &str, last);
1450 reg_num = next_field (str, ',', &str, last);
1452 fprintf (table, " { \"%s\",\n ", reg_name);
1454 process_i386_operand_type (table, reg_type, stage_registers, "\t",
1457 /* Find 32-bit Dwarf2 register number. */
1458 dw2_32_num = next_field (str, ',', &str, last);
1460 /* Find 64-bit Dwarf2 register number. */
1461 dw2_64_num = next_field (str, ',', &str, last);
1463 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1464 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1469 fprintf (table, "};\n");
1471 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1475 process_i386_initializers (void)
1478 FILE *fp = fopen ("i386-init.h", "w");
1482 fail (_("can't create i386-init.h, errno = %s\n"),
1485 process_copyright (fp);
1487 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1489 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1490 init = xstrdup (cpu_flag_init[i].init);
1491 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1495 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1497 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1498 init = xstrdup (operand_type_init[i].init);
1499 process_i386_operand_type (fp, init, stage_macros, " ", -1);
1507 /* Program options. */
1508 #define OPTION_SRCDIR 200
1510 struct option long_options[] =
1512 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1513 {"debug", no_argument, NULL, 'd'},
1514 {"version", no_argument, NULL, 'V'},
1515 {"help", no_argument, NULL, 'h'},
1516 {0, no_argument, NULL, 0}
1520 print_version (void)
1522 printf ("%s: version 1.0\n", program_name);
1527 usage (FILE * stream, int status)
1529 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1535 main (int argc, char **argv)
1537 extern int chdir (char *);
1538 char *srcdir = NULL;
1540 unsigned int i, cpumax;
1543 program_name = *argv;
1544 xmalloc_set_program_name (program_name);
1546 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1571 if (chdir (srcdir) != 0)
1572 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1573 srcdir, xstrerror (errno));
1575 /* cpu_flags isn't sorted by position. */
1577 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
1578 if (cpu_flags[i].position > cpumax)
1579 cpumax = cpu_flags[i].position;
1581 /* Check the unused bitfield in i386_cpu_flags. */
1583 if ((cpumax - 1) != CpuMax)
1584 fail (_("CpuMax != %d!\n"), cpumax);
1586 if (cpumax != CpuMax)
1587 fail (_("CpuMax != %d!\n"), cpumax);
1589 c = CpuNumOfBits - CpuMax - 1;
1591 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1594 /* Check the unused bitfield in i386_operand_type. */
1596 c = OTNumOfBits - OTMax - 1;
1598 fail (_("%d unused bits in i386_operand_type.\n"), c);
1601 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1604 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1605 sizeof (opcode_modifiers [0]), compare);
1607 qsort (operand_types, ARRAY_SIZE (operand_types),
1608 sizeof (operand_types [0]), compare);
1610 table = fopen ("i386-tbl.h", "w");
1612 fail (_("can't create i386-tbl.h, errno = %s\n"),
1615 process_copyright (table);
1617 process_i386_opcodes (table);
1618 process_i386_registers (table);
1619 process_i386_initializers ();