1 /* Copyright (C) 2007-2019 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 /* Build-time checks are preferrable over runtime ones. Use this construct
34 in preference where possible. */
35 #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
37 static const char *program_name
= NULL
;
40 typedef struct initializer
46 static initializer cpu_flag_init
[] =
48 { "CPU_UNKNOWN_FLAGS",
49 "~(CpuL1OM|CpuK1OM)" },
50 { "CPU_GENERIC32_FLAGS",
51 "Cpu186|Cpu286|Cpu386" },
52 { "CPU_GENERIC64_FLAGS",
53 "CPU_PENTIUMPRO_FLAGS|CpuClflush|CpuSYSCALL|CPU_MMX_FLAGS|CPU_SSE2_FLAGS|CpuLM" },
59 "CPU_I186_FLAGS|Cpu286" },
61 "CPU_I286_FLAGS|Cpu386" },
63 "CPU_I386_FLAGS|Cpu486" },
65 "CPU_I486_FLAGS|Cpu387|Cpu586" },
67 "CPU_I586_FLAGS|Cpu686|Cpu687|CpuCMOV|CpuFXSR" },
68 { "CPU_PENTIUMPRO_FLAGS",
69 "CPU_I686_FLAGS|CpuNop" },
71 "CPU_PENTIUMPRO_FLAGS|CPU_MMX_FLAGS" },
73 "CPU_P2_FLAGS|CPU_SSE_FLAGS" },
75 "CPU_P3_FLAGS|CpuClflush|CPU_SSE2_FLAGS" },
77 "CPU_GENERIC64_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
79 "CPU_P4_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
81 "CPU_NOCONA_FLAGS|CPU_SSSE3_FLAGS" },
83 "CPU_CORE2_FLAGS|CPU_SSE4_2_FLAGS|CpuRdtscp" },
85 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CPU_MMX_FLAGS" },
87 "CPU_K6_FLAGS|Cpu3dnow" },
89 "CPU_K6_2_FLAGS|Cpu686|Cpu687|CpuNop|Cpu3dnowA" },
91 "CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
92 { "CPU_AMDFAM10_FLAGS",
93 "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuABM" },
95 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuABM|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|CpuLZCNT|CpuPRFCHW" },
97 "CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
99 "CPU_BDVER2_FLAGS|CpuXsaveopt|CpuFSGSBase" },
100 { "CPU_BDVER4_FLAGS",
101 "CPU_BDVER3_FLAGS|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuMWAITX" },
102 { "CPU_ZNVER1_FLAGS",
103 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_AVX2_FLAGS|CpuSSE4A|CpuABM|CpuSVME|CpuAES|CpuPCLMUL|CpuLZCNT|CpuPRFCHW|CpuFMA|CpuBMI|CpuF16C|CpuXsaveopt|CpuFSGSBase|CpuMovbe|CpuBMI2|CpuRdRnd|CpuADX|CpuRdSeed|CpuSMAP|CpuSHA|CpuXSAVEC|CpuXSAVES|CpuClflushOpt|CpuCLZERO|CpuMWAITX" },
104 { "CPU_ZNVER2_FLAGS",
105 "CPU_ZNVER1_FLAGS|CpuRDPID|CpuWBNOINVD|CpuCLWB" },
106 { "CPU_BTVER1_FLAGS",
107 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuABM|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME|CpuLZCNT" },
108 { "CPU_BTVER2_FLAGS",
109 "CPU_BTVER1_FLAGS|CPU_AVX_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuMovbe|CpuXsaveopt|CpuPRFCHW" },
117 "CPU_387_FLAGS|Cpu687" },
122 { "CPU_CLFLUSH_FLAGS",
126 { "CPU_SYSCALL_FLAGS",
133 "CPU_SSE_FLAGS|CpuSSE2" },
135 "CPU_SSE2_FLAGS|CpuSSE3" },
137 "CPU_SSE3_FLAGS|CpuSSSE3" },
138 { "CPU_SSE4_1_FLAGS",
139 "CPU_SSSE3_FLAGS|CpuSSE4_1" },
140 { "CPU_SSE4_2_FLAGS",
141 "CPU_SSE4_1_FLAGS|CpuSSE4_2" },
148 { "CPU_XSAVEOPT_FLAGS",
149 "CPU_XSAVE_FLAGS|CpuXsaveopt" },
151 "CPU_SSE2_FLAGS|CpuAES" },
152 { "CPU_PCLMUL_FLAGS",
153 "CPU_SSE2_FLAGS|CpuPCLMUL" },
155 "CPU_AVX_FLAGS|CpuFMA" },
157 "CPU_AVX_FLAGS|CpuFMA4" },
159 "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
161 "CPU_XSAVE_FLAGS|CpuLWP" },
170 { "CPU_RDTSCP_FLAGS",
174 { "CPU_FSGSBASE_FLAGS",
179 "CPU_AVX_FLAGS|CpuF16C" },
188 { "CPU_INVPCID_FLAGS",
190 { "CPU_VMFUNC_FLAGS",
193 "CPU_MMX_FLAGS|Cpu3dnow" },
194 { "CPU_3DNOWA_FLAGS",
195 "CPU_3DNOW_FLAGS|Cpu3dnowA" },
196 { "CPU_PADLOCK_FLAGS",
201 "CPU_SSE3_FLAGS|CpuSSE4a" },
205 "CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
207 "CPU_AVX_FLAGS|CpuAVX2" },
208 { "CPU_AVX512F_FLAGS",
209 "CPU_AVX2_FLAGS|CpuAVX512F" },
210 { "CPU_AVX512CD_FLAGS",
211 "CPU_AVX512F_FLAGS|CpuAVX512CD" },
212 { "CPU_AVX512ER_FLAGS",
213 "CPU_AVX512F_FLAGS|CpuAVX512ER" },
214 { "CPU_AVX512PF_FLAGS",
215 "CPU_AVX512F_FLAGS|CpuAVX512PF" },
216 { "CPU_AVX512DQ_FLAGS",
217 "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
218 { "CPU_AVX512BW_FLAGS",
219 "CPU_AVX512F_FLAGS|CpuAVX512BW" },
220 { "CPU_AVX512VL_FLAGS",
221 "CPU_AVX512F_FLAGS|CpuAVX512VL" },
222 { "CPU_AVX512IFMA_FLAGS",
223 "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
224 { "CPU_AVX512VBMI_FLAGS",
225 "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
226 { "CPU_AVX512_4FMAPS_FLAGS",
227 "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
228 { "CPU_AVX512_4VNNIW_FLAGS",
229 "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
230 { "CPU_AVX512_VPOPCNTDQ_FLAGS",
231 "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
232 { "CPU_AVX512_VBMI2_FLAGS",
233 "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
234 { "CPU_AVX512_VNNI_FLAGS",
235 "CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
236 { "CPU_AVX512_BITALG_FLAGS",
237 "CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
238 { "CPU_AVX512_BF16_FLAGS",
239 "CPU_AVX512F_FLAGS|CpuAVX512_BF16" },
245 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
248 { "CPU_RDSEED_FLAGS",
250 { "CPU_PRFCHW_FLAGS",
255 "CPU_XSAVE_FLAGS|CpuMPX" },
257 "CPU_SSE2_FLAGS|CpuSHA" },
258 { "CPU_CLFLUSHOPT_FLAGS",
260 { "CPU_XSAVES_FLAGS",
261 "CPU_XSAVE_FLAGS|CpuXSAVES" },
262 { "CPU_XSAVEC_FLAGS",
263 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
264 { "CPU_PREFETCHWT1_FLAGS",
270 { "CPU_CLZERO_FLAGS",
272 { "CPU_MWAITX_FLAGS",
275 "CPU_XSAVE_FLAGS|CpuOSPKE" },
278 { "CPU_PTWRITE_FLAGS",
288 { "CPU_VPCLMULQDQ_FLAGS",
290 { "CPU_WBNOINVD_FLAGS",
292 { "CPU_PCONFIG_FLAGS",
294 { "CPU_WAITPKG_FLAGS",
296 { "CPU_CLDEMOTE_FLAGS",
298 { "CPU_MOVDIRI_FLAGS",
300 { "CPU_MOVDIR64B_FLAGS",
302 { "CPU_ENQCMD_FLAGS",
304 { "CPU_AVX512_VP2INTERSECT_FLAGS",
305 "CpuAVX512_VP2INTERSECT" },
306 { "CPU_ANY_X87_FLAGS",
307 "CPU_ANY_287_FLAGS|Cpu8087" },
308 { "CPU_ANY_287_FLAGS",
309 "CPU_ANY_387_FLAGS|Cpu287" },
310 { "CPU_ANY_387_FLAGS",
311 "CPU_ANY_687_FLAGS|Cpu387" },
312 { "CPU_ANY_687_FLAGS",
313 "Cpu687|CpuFISTTP" },
314 { "CPU_ANY_CMOV_FLAGS",
316 { "CPU_ANY_FXSR_FLAGS",
318 { "CPU_ANY_MMX_FLAGS",
319 "CPU_3DNOWA_FLAGS" },
320 { "CPU_ANY_SSE_FLAGS",
321 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
322 { "CPU_ANY_SSE2_FLAGS",
323 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
324 { "CPU_ANY_SSE3_FLAGS",
325 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
326 { "CPU_ANY_SSSE3_FLAGS",
327 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
328 { "CPU_ANY_SSE4_1_FLAGS",
329 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
330 { "CPU_ANY_SSE4_2_FLAGS",
332 { "CPU_ANY_AVX_FLAGS",
333 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
334 { "CPU_ANY_AVX2_FLAGS",
335 "CPU_ANY_AVX512F_FLAGS|CpuAVX2" },
336 { "CPU_ANY_AVX512F_FLAGS",
337 "CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_BF16|CpuAVX512_VP2INTERSECT" },
338 { "CPU_ANY_AVX512CD_FLAGS",
340 { "CPU_ANY_AVX512ER_FLAGS",
342 { "CPU_ANY_AVX512PF_FLAGS",
344 { "CPU_ANY_AVX512DQ_FLAGS",
346 { "CPU_ANY_AVX512BW_FLAGS",
348 { "CPU_ANY_AVX512VL_FLAGS",
350 { "CPU_ANY_AVX512IFMA_FLAGS",
352 { "CPU_ANY_AVX512VBMI_FLAGS",
354 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
355 "CpuAVX512_4FMAPS" },
356 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
357 "CpuAVX512_4VNNIW" },
358 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
359 "CpuAVX512_VPOPCNTDQ" },
360 { "CPU_ANY_IBT_FLAGS",
362 { "CPU_ANY_SHSTK_FLAGS",
364 { "CPU_ANY_AVX512_VBMI2_FLAGS",
366 { "CPU_ANY_AVX512_VNNI_FLAGS",
368 { "CPU_ANY_AVX512_BITALG_FLAGS",
369 "CpuAVX512_BITALG" },
370 { "CPU_ANY_AVX512_BF16_FLAGS",
372 { "CPU_ANY_MOVDIRI_FLAGS",
374 { "CPU_ANY_MOVDIR64B_FLAGS",
376 { "CPU_ANY_ENQCMD_FLAGS",
378 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
379 "CpuAVX512_VP2INTERSECT" },
382 static initializer operand_type_init
[] =
384 { "OPERAND_TYPE_NONE",
386 { "OPERAND_TYPE_REG8",
388 { "OPERAND_TYPE_REG16",
390 { "OPERAND_TYPE_REG32",
392 { "OPERAND_TYPE_REG64",
394 { "OPERAND_TYPE_IMM1",
396 { "OPERAND_TYPE_IMM8",
398 { "OPERAND_TYPE_IMM8S",
400 { "OPERAND_TYPE_IMM16",
402 { "OPERAND_TYPE_IMM32",
404 { "OPERAND_TYPE_IMM32S",
406 { "OPERAND_TYPE_IMM64",
408 { "OPERAND_TYPE_BASEINDEX",
410 { "OPERAND_TYPE_DISP8",
412 { "OPERAND_TYPE_DISP16",
414 { "OPERAND_TYPE_DISP32",
416 { "OPERAND_TYPE_DISP32S",
418 { "OPERAND_TYPE_DISP64",
420 { "OPERAND_TYPE_INOUTPORTREG",
422 { "OPERAND_TYPE_SHIFTCOUNT",
424 { "OPERAND_TYPE_CONTROL",
426 { "OPERAND_TYPE_TEST",
428 { "OPERAND_TYPE_DEBUG",
430 { "OPERAND_TYPE_FLOATREG",
432 { "OPERAND_TYPE_FLOATACC",
434 { "OPERAND_TYPE_SREG",
436 { "OPERAND_TYPE_JUMPABSOLUTE",
438 { "OPERAND_TYPE_REGMMX",
440 { "OPERAND_TYPE_REGXMM",
442 { "OPERAND_TYPE_REGYMM",
444 { "OPERAND_TYPE_REGZMM",
446 { "OPERAND_TYPE_REGMASK",
448 { "OPERAND_TYPE_ESSEG",
450 { "OPERAND_TYPE_ACC8",
452 { "OPERAND_TYPE_ACC16",
454 { "OPERAND_TYPE_ACC32",
456 { "OPERAND_TYPE_ACC64",
458 { "OPERAND_TYPE_DISP16_32",
460 { "OPERAND_TYPE_ANYDISP",
461 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
462 { "OPERAND_TYPE_IMM16_32",
464 { "OPERAND_TYPE_IMM16_32S",
466 { "OPERAND_TYPE_IMM16_32_32S",
467 "Imm16|Imm32|Imm32S" },
468 { "OPERAND_TYPE_IMM32_64",
470 { "OPERAND_TYPE_IMM32_32S_DISP32",
471 "Imm32|Imm32S|Disp32" },
472 { "OPERAND_TYPE_IMM64_DISP64",
474 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
475 "Imm32|Imm32S|Imm64|Disp32" },
476 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
477 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
478 { "OPERAND_TYPE_REGBND",
482 typedef struct bitfield
489 #define BITFIELD(n) { n, 0, #n }
491 static bitfield cpu_flags
[] =
501 BITFIELD (CpuClflush
),
503 BITFIELD (CpuSYSCALL
),
508 BITFIELD (CpuFISTTP
),
514 BITFIELD (CpuSSE4_1
),
515 BITFIELD (CpuSSE4_2
),
518 BITFIELD (CpuAVX512F
),
519 BITFIELD (CpuAVX512CD
),
520 BITFIELD (CpuAVX512ER
),
521 BITFIELD (CpuAVX512PF
),
522 BITFIELD (CpuAVX512VL
),
523 BITFIELD (CpuAVX512DQ
),
524 BITFIELD (CpuAVX512BW
),
530 BITFIELD (Cpu3dnowA
),
531 BITFIELD (CpuPadLock
),
537 BITFIELD (CpuXsaveopt
),
539 BITFIELD (CpuPCLMUL
),
550 BITFIELD (CpuRdtscp
),
551 BITFIELD (CpuFSGSBase
),
558 BITFIELD (CpuINVPCID
),
559 BITFIELD (CpuVMFUNC
),
560 BITFIELD (CpuRDSEED
),
562 BITFIELD (CpuPRFCHW
),
565 BITFIELD (CpuClflushOpt
),
566 BITFIELD (CpuXSAVES
),
567 BITFIELD (CpuXSAVEC
),
568 BITFIELD (CpuPREFETCHWT1
),
574 BITFIELD (CpuAVX512IFMA
),
575 BITFIELD (CpuAVX512VBMI
),
576 BITFIELD (CpuAVX512_4FMAPS
),
577 BITFIELD (CpuAVX512_4VNNIW
),
578 BITFIELD (CpuAVX512_VPOPCNTDQ
),
579 BITFIELD (CpuAVX512_VBMI2
),
580 BITFIELD (CpuAVX512_VNNI
),
581 BITFIELD (CpuAVX512_BITALG
),
582 BITFIELD (CpuAVX512_BF16
),
583 BITFIELD (CpuAVX512_VP2INTERSECT
),
584 BITFIELD (CpuMWAITX
),
585 BITFIELD (CpuCLZERO
),
588 BITFIELD (CpuPTWRITE
),
593 BITFIELD (CpuVPCLMULQDQ
),
594 BITFIELD (CpuWBNOINVD
),
595 BITFIELD (CpuPCONFIG
),
596 BITFIELD (CpuWAITPKG
),
597 BITFIELD (CpuCLDEMOTE
),
598 BITFIELD (CpuMOVDIRI
),
599 BITFIELD (CpuMOVDIR64B
),
600 BITFIELD (CpuENQCMD
),
602 BITFIELD (CpuUnused
),
606 static bitfield opcode_modifiers
[] =
612 BITFIELD (ShortForm
),
614 BITFIELD (JumpDword
),
616 BITFIELD (JumpInterSegment
),
620 BITFIELD (CheckRegSize
),
621 BITFIELD (IgnoreSize
),
622 BITFIELD (DefaultSize
),
632 BITFIELD (BNDPrefixOk
),
633 BITFIELD (NoTrackPrefixOk
),
634 BITFIELD (IsLockable
),
635 BITFIELD (RegKludge
),
636 BITFIELD (Implicit1stXmm0
),
637 BITFIELD (RepPrefixOk
),
638 BITFIELD (HLEPrefixOk
),
641 BITFIELD (AddrPrefixOpReg
),
650 BITFIELD (VexOpcode
),
651 BITFIELD (VexSources
),
657 BITFIELD (Broadcast
),
658 BITFIELD (StaticRounding
),
660 BITFIELD (Disp8MemShift
),
661 BITFIELD (NoDefMask
),
662 BITFIELD (ImplicitQuadGroup
),
664 BITFIELD (ATTMnemonic
),
665 BITFIELD (ATTSyntax
),
666 BITFIELD (IntelSyntax
),
671 static bitfield operand_types
[] =
684 BITFIELD (BaseIndex
),
690 BITFIELD (InOutPortReg
),
691 BITFIELD (ShiftCount
),
697 BITFIELD (JumpAbsolute
),
708 BITFIELD (Unspecified
),
716 static const char *filename
;
717 static i386_cpu_flags active_cpu_flags
;
718 static int active_isstring
;
721 compare (const void *x
, const void *y
)
723 const bitfield
*xp
= (const bitfield
*) x
;
724 const bitfield
*yp
= (const bitfield
*) y
;
725 return xp
->position
- yp
->position
;
729 fail (const char *message
, ...)
733 va_start (args
, message
);
734 fprintf (stderr
, _("%s: error: "), program_name
);
735 vfprintf (stderr
, message
, args
);
741 process_copyright (FILE *fp
)
743 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
744 /* Copyright (C) 2007-2019 Free Software Foundation, Inc.\n\
746 This file is part of the GNU opcodes library.\n\
748 This library is free software; you can redistribute it and/or modify\n\
749 it under the terms of the GNU General Public License as published by\n\
750 the Free Software Foundation; either version 3, or (at your option)\n\
751 any later version.\n\
753 It is distributed in the hope that it will be useful, but WITHOUT\n\
754 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
755 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
756 License for more details.\n\
758 You should have received a copy of the GNU General Public License\n\
759 along with this program; if not, write to the Free Software\n\
760 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
761 MA 02110-1301, USA. */\n");
764 /* Remove leading white spaces. */
767 remove_leading_whitespaces (char *str
)
769 while (ISSPACE (*str
))
774 /* Remove trailing white spaces. */
777 remove_trailing_whitespaces (char *str
)
779 size_t last
= strlen (str
);
787 if (ISSPACE (str
[last
]))
795 /* Find next field separated by SEP and terminate it. Return a
796 pointer to the one after it. */
799 next_field (char *str
, char sep
, char **next
, char *last
)
803 p
= remove_leading_whitespaces (str
);
804 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
807 remove_trailing_whitespaces (p
);
817 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
820 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
823 char *str
, *next
, *last
;
826 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
827 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
829 /* Turn on selective bits. */
830 char *init
= xstrdup (cpu_flag_init
[i
].init
);
831 last
= init
+ strlen (init
);
832 for (next
= init
; next
&& next
< last
; )
834 str
= next_field (next
, '|', &next
, last
);
836 set_bitfield (str
, array
, 1, size
, lineno
);
846 set_bitfield (char *f
, bitfield
*array
, int value
,
847 unsigned int size
, int lineno
)
851 if (strcmp (f
, "CpuFP") == 0)
853 set_bitfield("Cpu387", array
, value
, size
, lineno
);
854 set_bitfield("Cpu287", array
, value
, size
, lineno
);
857 else if (strcmp (f
, "Mmword") == 0)
859 else if (strcmp (f
, "Oword") == 0)
862 for (i
= 0; i
< size
; i
++)
863 if (strcasecmp (array
[i
].name
, f
) == 0)
865 array
[i
].value
= value
;
871 const char *v
= strchr (f
, '=');
878 for (i
= 0; i
< size
; i
++)
879 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
881 value
= strtol (v
+ 1, &end
, 0);
884 array
[i
].value
= value
;
892 /* Handle CPU_XXX_FLAGS. */
893 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
897 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
899 fail (_("unknown bitfield: %s\n"), f
);
903 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
904 int macro
, const char *comma
, const char *indent
)
908 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
910 fprintf (table
, "%s{ { ", indent
);
912 for (i
= 0; i
< size
- 1; i
++)
914 if (((i
+ 1) % 20) != 0)
915 fprintf (table
, "%d, ", flags
[i
].value
);
917 fprintf (table
, "%d,", flags
[i
].value
);
918 if (((i
+ 1) % 20) == 0)
920 /* We need \\ for macro. */
922 fprintf (table
, " \\\n %s", indent
);
924 fprintf (table
, "\n %s", indent
);
927 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
930 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
934 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
935 const char *comma
, const char *indent
,
938 char *str
, *next
, *last
;
940 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
942 /* Copy the default cpu flags. */
943 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
945 if (strcasecmp (flag
, "unknown") == 0)
947 /* We turn on everything except for cpu64 in case of
948 CPU_UNKNOWN_FLAGS. */
949 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
950 if (flags
[i
].position
!= Cpu64
)
953 else if (flag
[0] == '~')
955 last
= flag
+ strlen (flag
);
962 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
969 /* First we turn on everything except for cpu64. */
970 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
971 if (flags
[i
].position
!= Cpu64
)
974 /* Turn off selective bits. */
975 for (; next
&& next
< last
; )
977 str
= next_field (next
, '|', &next
, last
);
979 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
982 else if (strcmp (flag
, "0"))
984 /* Turn on selective bits. */
985 last
= flag
+ strlen (flag
);
986 for (next
= flag
; next
&& next
< last
; )
988 str
= next_field (next
, '|', &next
, last
);
990 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
994 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
999 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1003 fprintf (table
, " { ");
1005 for (i
= 0; i
< size
- 1; i
++)
1007 if (((i
+ 1) % 20) != 0)
1008 fprintf (table
, "%d, ", modifier
[i
].value
);
1010 fprintf (table
, "%d,", modifier
[i
].value
);
1011 if (((i
+ 1) % 20) == 0)
1012 fprintf (table
, "\n ");
1015 fprintf (table
, "%d },\n", modifier
[i
].value
);
1019 adjust_broadcast_modifier (char **opnd
)
1021 char *str
, *next
, *last
, *op
;
1022 int bcst_type
= INT_MAX
;
1024 /* Skip the immediate operand. */
1026 if (strcasecmp(op
, "Imm8") == 0)
1030 last
= op
+ strlen (op
);
1031 for (next
= op
; next
&& next
< last
; )
1033 str
= next_field (next
, '|', &next
, last
);
1036 if (strcasecmp(str
, "Byte") == 0)
1038 /* The smalest broadcast type, no need to check
1040 bcst_type
= BYTE_BROADCAST
;
1043 else if (strcasecmp(str
, "Word") == 0)
1045 if (bcst_type
> WORD_BROADCAST
)
1046 bcst_type
= WORD_BROADCAST
;
1048 else if (strcasecmp(str
, "Dword") == 0)
1050 if (bcst_type
> DWORD_BROADCAST
)
1051 bcst_type
= DWORD_BROADCAST
;
1053 else if (strcasecmp(str
, "Qword") == 0)
1055 if (bcst_type
> QWORD_BROADCAST
)
1056 bcst_type
= QWORD_BROADCAST
;
1062 if (bcst_type
== INT_MAX
)
1063 fail (_("unknown broadcast operand: %s\n"), op
);
1069 process_i386_opcode_modifier (FILE *table
, char *mod
, char **opnd
, int lineno
)
1071 char *str
, *next
, *last
;
1072 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1074 active_isstring
= 0;
1076 /* Copy the default opcode modifier. */
1077 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1079 if (strcmp (mod
, "0"))
1081 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1083 last
= mod
+ strlen (mod
);
1084 for (next
= mod
; next
&& next
< last
; )
1086 str
= next_field (next
, '|', &next
, last
);
1090 if (strcasecmp(str
, "Broadcast") == 0)
1091 val
= adjust_broadcast_modifier (opnd
);
1092 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1094 if (strcasecmp(str
, "IsString") == 0)
1095 active_isstring
= 1;
1097 if (strcasecmp(str
, "W") == 0)
1100 if (strcasecmp(str
, "No_bSuf") == 0)
1102 if (strcasecmp(str
, "No_wSuf") == 0)
1104 if (strcasecmp(str
, "No_lSuf") == 0)
1106 if (strcasecmp(str
, "No_qSuf") == 0)
1111 if (have_w
&& !bwlq_suf
)
1112 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1113 if (have_w
&& !(bwlq_suf
& 1))
1114 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1116 if (have_w
&& !(bwlq_suf
& ~1))
1118 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1121 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1131 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
1132 enum stage stage
, const char *indent
)
1136 fprintf (table
, "{ { ");
1138 for (i
= 0; i
< size
- 1; i
++)
1140 if (((i
+ 1) % 20) != 0)
1141 fprintf (table
, "%d, ", types
[i
].value
);
1143 fprintf (table
, "%d,", types
[i
].value
);
1144 if (((i
+ 1) % 20) == 0)
1146 /* We need \\ for macro. */
1147 if (stage
== stage_macros
)
1148 fprintf (table
, " \\\n%s", indent
);
1150 fprintf (table
, "\n%s", indent
);
1154 fprintf (table
, "%d } }", types
[i
].value
);
1158 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1159 const char *indent
, int lineno
)
1161 char *str
, *next
, *last
;
1162 bitfield types
[ARRAY_SIZE (operand_types
)];
1164 /* Copy the default operand type. */
1165 memcpy (types
, operand_types
, sizeof (types
));
1167 if (strcmp (op
, "0"))
1171 last
= op
+ strlen (op
);
1172 for (next
= op
; next
&& next
< last
; )
1174 str
= next_field (next
, '|', &next
, last
);
1177 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1178 if (strcasecmp(str
, "BaseIndex") == 0)
1183 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1185 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1186 if (!active_cpu_flags
.bitfield
.cpu64
1187 && !active_cpu_flags
.bitfield
.cpumpx
)
1188 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1189 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1190 if (!active_cpu_flags
.bitfield
.cpuno64
)
1191 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1194 output_operand_type (table
, types
, ARRAY_SIZE (types
), stage
,
1199 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1200 char *last
, int lineno
)
1203 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1204 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1206 /* Find number of operands. */
1207 operands
= next_field (str
, ',', &str
, last
);
1209 /* Find base_opcode. */
1210 base_opcode
= next_field (str
, ',', &str
, last
);
1212 /* Find extension_opcode. */
1213 extension_opcode
= next_field (str
, ',', &str
, last
);
1215 /* Find opcode_length. */
1216 opcode_length
= next_field (str
, ',', &str
, last
);
1218 /* Find cpu_flags. */
1219 cpu_flags
= next_field (str
, ',', &str
, last
);
1221 /* Find opcode_modifier. */
1222 opcode_modifier
= next_field (str
, ',', &str
, last
);
1224 /* Remove the first {. */
1225 str
= remove_leading_whitespaces (str
);
1228 str
= remove_leading_whitespaces (str
+ 1);
1232 /* There are at least "X}". */
1236 /* Remove trailing white spaces and }. */
1240 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1249 /* Find operand_types. */
1250 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1254 operand_types
[i
] = NULL
;
1258 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1259 if (*operand_types
[i
] == '0')
1262 operand_types
[i
] = NULL
;
1267 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1268 name
, base_opcode
, extension_opcode
, opcode_length
, operands
);
1270 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1272 process_i386_opcode_modifier (table
, opcode_modifier
, operand_types
, lineno
);
1274 fprintf (table
, " { ");
1276 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1278 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1281 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1287 fprintf (table
, ",\n ");
1289 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1292 fprintf (table
, " } },\n");
1295 struct opcode_hash_entry
1297 struct opcode_hash_entry
*next
;
1303 /* Calculate the hash value of an opcode hash entry P. */
1306 opcode_hash_hash (const void *p
)
1308 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1309 return htab_hash_string (entry
->name
);
1312 /* Compare a string Q against an opcode hash entry P. */
1315 opcode_hash_eq (const void *p
, const void *q
)
1317 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1318 const char *name
= (const char *) q
;
1319 return strcmp (name
, entry
->name
) == 0;
1323 process_i386_opcodes (FILE *table
)
1328 char *str
, *p
, *last
, *name
;
1329 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1330 htab_t opcode_hash_table
;
1331 struct opcode_hash_entry
**opcode_array
;
1332 unsigned int opcode_array_size
= 1024;
1333 int lineno
= 0, marker
= 0;
1335 filename
= "i386-opc.tbl";
1339 opcode_array
= (struct opcode_hash_entry
**)
1340 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1342 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1343 opcode_hash_eq
, NULL
,
1346 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1347 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1349 /* Put everything on opcode array. */
1352 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1357 p
= remove_leading_whitespaces (buf
);
1359 /* Skip comments. */
1360 str
= strstr (p
, "//");
1364 /* Remove trailing white spaces. */
1365 remove_trailing_whitespaces (p
);
1370 if (!strcmp("### MARKER ###", buf
))
1374 /* Since we ignore all included files (we only care about their
1375 #define-s here), we don't need to monitor filenames. The final
1376 line number directive is going to refer to the main source file
1381 p
= remove_leading_whitespaces (p
+ 1);
1382 if (!strncmp(p
, "line", 4))
1384 ln
= strtoul (p
, &end
, 10);
1385 if (ln
> 1 && ln
< INT_MAX
1386 && *remove_leading_whitespaces (end
) == '"')
1389 /* Ignore comments. */
1399 last
= p
+ strlen (p
);
1402 name
= next_field (p
, ',', &str
, last
);
1404 /* Get the slot in hash table. */
1405 hash_slot
= (struct opcode_hash_entry
**)
1406 htab_find_slot_with_hash (opcode_hash_table
, name
,
1407 htab_hash_string (name
),
1410 if (*hash_slot
== NULL
)
1412 /* It is the new one. Put it on opcode array. */
1413 if (i
>= opcode_array_size
)
1415 /* Grow the opcode array when needed. */
1416 opcode_array_size
+= 1024;
1417 opcode_array
= (struct opcode_hash_entry
**)
1418 xrealloc (opcode_array
,
1419 sizeof (*opcode_array
) * opcode_array_size
);
1422 opcode_array
[i
] = (struct opcode_hash_entry
*)
1423 xmalloc (sizeof (struct opcode_hash_entry
));
1424 opcode_array
[i
]->next
= NULL
;
1425 opcode_array
[i
]->name
= xstrdup (name
);
1426 opcode_array
[i
]->opcode
= xstrdup (str
);
1427 opcode_array
[i
]->lineno
= lineno
;
1428 *hash_slot
= opcode_array
[i
];
1433 /* Append it to the existing one. */
1435 while ((*entry
) != NULL
)
1436 entry
= &(*entry
)->next
;
1437 *entry
= (struct opcode_hash_entry
*)
1438 xmalloc (sizeof (struct opcode_hash_entry
));
1439 (*entry
)->next
= NULL
;
1440 (*entry
)->name
= (*hash_slot
)->name
;
1441 (*entry
)->opcode
= xstrdup (str
);
1442 (*entry
)->lineno
= lineno
;
1446 /* Process opcode array. */
1447 for (j
= 0; j
< i
; j
++)
1449 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1453 lineno
= next
->lineno
;
1454 last
= str
+ strlen (str
);
1455 output_i386_opcode (table
, name
, str
, last
, lineno
);
1461 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1463 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1465 process_i386_opcode_modifier (table
, "0", NULL
, -1);
1467 fprintf (table
, " { ");
1468 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1469 fprintf (table
, " } }\n");
1471 fprintf (table
, "};\n");
1475 process_i386_registers (FILE *table
)
1479 char *str
, *p
, *last
;
1480 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1481 char *dw2_32_num
, *dw2_64_num
;
1484 filename
= "i386-reg.tbl";
1485 fp
= fopen (filename
, "r");
1487 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1490 fprintf (table
, "\n/* i386 register table. */\n\n");
1491 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1495 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1500 p
= remove_leading_whitespaces (buf
);
1502 /* Skip comments. */
1503 str
= strstr (p
, "//");
1507 /* Remove trailing white spaces. */
1508 remove_trailing_whitespaces (p
);
1513 fprintf (table
, "%s\n", p
);
1521 last
= p
+ strlen (p
);
1523 /* Find reg_name. */
1524 reg_name
= next_field (p
, ',', &str
, last
);
1526 /* Find reg_type. */
1527 reg_type
= next_field (str
, ',', &str
, last
);
1529 /* Find reg_flags. */
1530 reg_flags
= next_field (str
, ',', &str
, last
);
1533 reg_num
= next_field (str
, ',', &str
, last
);
1535 fprintf (table
, " { \"%s\",\n ", reg_name
);
1537 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1540 /* Find 32-bit Dwarf2 register number. */
1541 dw2_32_num
= next_field (str
, ',', &str
, last
);
1543 /* Find 64-bit Dwarf2 register number. */
1544 dw2_64_num
= next_field (str
, ',', &str
, last
);
1546 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1547 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1552 fprintf (table
, "};\n");
1554 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1558 process_i386_initializers (void)
1561 FILE *fp
= fopen ("i386-init.h", "w");
1565 fail (_("can't create i386-init.h, errno = %s\n"),
1568 process_copyright (fp
);
1570 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1572 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1573 init
= xstrdup (cpu_flag_init
[i
].init
);
1574 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1578 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1580 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1581 init
= xstrdup (operand_type_init
[i
].init
);
1582 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1590 /* Program options. */
1591 #define OPTION_SRCDIR 200
1593 struct option long_options
[] =
1595 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1596 {"debug", no_argument
, NULL
, 'd'},
1597 {"version", no_argument
, NULL
, 'V'},
1598 {"help", no_argument
, NULL
, 'h'},
1599 {0, no_argument
, NULL
, 0}
1603 print_version (void)
1605 printf ("%s: version 1.0\n", program_name
);
1610 usage (FILE * stream
, int status
)
1612 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1618 main (int argc
, char **argv
)
1620 extern int chdir (char *);
1621 char *srcdir
= NULL
;
1623 unsigned int i
, cpumax
;
1626 program_name
= *argv
;
1627 xmalloc_set_program_name (program_name
);
1629 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1654 if (chdir (srcdir
) != 0)
1655 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1656 srcdir
, xstrerror (errno
));
1658 /* cpu_flags isn't sorted by position. */
1660 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1661 if (cpu_flags
[i
].position
> cpumax
)
1662 cpumax
= cpu_flags
[i
].position
;
1664 /* Check the unused bitfield in i386_cpu_flags. */
1666 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
1668 if ((cpumax
- 1) != CpuMax
)
1669 fail (_("CpuMax != %d!\n"), cpumax
);
1671 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
1673 if (cpumax
!= CpuMax
)
1674 fail (_("CpuMax != %d!\n"), cpumax
);
1676 c
= CpuNumOfBits
- CpuMax
- 1;
1678 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1681 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
1683 /* Check the unused bitfield in i386_operand_type. */
1685 static_assert (ARRAY_SIZE (operand_types
) == OTNum
+ 1);
1687 static_assert (ARRAY_SIZE (operand_types
) == OTNum
);
1689 c
= OTNumOfBits
- OTMax
- 1;
1691 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1694 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1697 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1698 sizeof (opcode_modifiers
[0]), compare
);
1700 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1701 sizeof (operand_types
[0]), compare
);
1703 table
= fopen ("i386-tbl.h", "w");
1705 fail (_("can't create i386-tbl.h, errno = %s\n"),
1708 process_copyright (table
);
1710 process_i386_opcodes (table
);
1711 process_i386_registers (table
);
1712 process_i386_initializers ();