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|CpuCLWB|CpuRDPID|CpuRDPRU|CpuMCOMMIT|CpuWBNOINVD" },
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" },
308 { "CPU_MCOMMIT_FLAGS",
310 { "CPU_ANY_X87_FLAGS",
311 "CPU_ANY_287_FLAGS|Cpu8087" },
312 { "CPU_ANY_287_FLAGS",
313 "CPU_ANY_387_FLAGS|Cpu287" },
314 { "CPU_ANY_387_FLAGS",
315 "CPU_ANY_687_FLAGS|Cpu387" },
316 { "CPU_ANY_687_FLAGS",
317 "Cpu687|CpuFISTTP" },
318 { "CPU_ANY_CMOV_FLAGS",
320 { "CPU_ANY_FXSR_FLAGS",
322 { "CPU_ANY_MMX_FLAGS",
323 "CPU_3DNOWA_FLAGS" },
324 { "CPU_ANY_SSE_FLAGS",
325 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
326 { "CPU_ANY_SSE2_FLAGS",
327 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
328 { "CPU_ANY_SSE3_FLAGS",
329 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
330 { "CPU_ANY_SSSE3_FLAGS",
331 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
332 { "CPU_ANY_SSE4_1_FLAGS",
333 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
334 { "CPU_ANY_SSE4_2_FLAGS",
336 { "CPU_ANY_AVX_FLAGS",
337 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
338 { "CPU_ANY_AVX2_FLAGS",
339 "CPU_ANY_AVX512F_FLAGS|CpuAVX2" },
340 { "CPU_ANY_AVX512F_FLAGS",
341 "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" },
342 { "CPU_ANY_AVX512CD_FLAGS",
344 { "CPU_ANY_AVX512ER_FLAGS",
346 { "CPU_ANY_AVX512PF_FLAGS",
348 { "CPU_ANY_AVX512DQ_FLAGS",
350 { "CPU_ANY_AVX512BW_FLAGS",
352 { "CPU_ANY_AVX512VL_FLAGS",
354 { "CPU_ANY_AVX512IFMA_FLAGS",
356 { "CPU_ANY_AVX512VBMI_FLAGS",
358 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
359 "CpuAVX512_4FMAPS" },
360 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
361 "CpuAVX512_4VNNIW" },
362 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
363 "CpuAVX512_VPOPCNTDQ" },
364 { "CPU_ANY_IBT_FLAGS",
366 { "CPU_ANY_SHSTK_FLAGS",
368 { "CPU_ANY_AVX512_VBMI2_FLAGS",
370 { "CPU_ANY_AVX512_VNNI_FLAGS",
372 { "CPU_ANY_AVX512_BITALG_FLAGS",
373 "CpuAVX512_BITALG" },
374 { "CPU_ANY_AVX512_BF16_FLAGS",
376 { "CPU_ANY_MOVDIRI_FLAGS",
378 { "CPU_ANY_MOVDIR64B_FLAGS",
380 { "CPU_ANY_ENQCMD_FLAGS",
382 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
383 "CpuAVX512_VP2INTERSECT" },
386 static initializer operand_type_init
[] =
388 { "OPERAND_TYPE_NONE",
390 { "OPERAND_TYPE_REG8",
392 { "OPERAND_TYPE_REG16",
394 { "OPERAND_TYPE_REG32",
396 { "OPERAND_TYPE_REG64",
398 { "OPERAND_TYPE_IMM1",
400 { "OPERAND_TYPE_IMM8",
402 { "OPERAND_TYPE_IMM8S",
404 { "OPERAND_TYPE_IMM16",
406 { "OPERAND_TYPE_IMM32",
408 { "OPERAND_TYPE_IMM32S",
410 { "OPERAND_TYPE_IMM64",
412 { "OPERAND_TYPE_BASEINDEX",
414 { "OPERAND_TYPE_DISP8",
416 { "OPERAND_TYPE_DISP16",
418 { "OPERAND_TYPE_DISP32",
420 { "OPERAND_TYPE_DISP32S",
422 { "OPERAND_TYPE_DISP64",
424 { "OPERAND_TYPE_INOUTPORTREG",
426 { "OPERAND_TYPE_SHIFTCOUNT",
428 { "OPERAND_TYPE_CONTROL",
430 { "OPERAND_TYPE_TEST",
432 { "OPERAND_TYPE_DEBUG",
434 { "OPERAND_TYPE_FLOATREG",
436 { "OPERAND_TYPE_FLOATACC",
438 { "OPERAND_TYPE_SREG",
440 { "OPERAND_TYPE_JUMPABSOLUTE",
442 { "OPERAND_TYPE_REGMMX",
444 { "OPERAND_TYPE_REGXMM",
445 "Class=RegSIMD|Xmmword" },
446 { "OPERAND_TYPE_REGYMM",
447 "Class=RegSIMD|Ymmword" },
448 { "OPERAND_TYPE_REGZMM",
449 "Class=RegSIMD|Zmmword" },
450 { "OPERAND_TYPE_REGMASK",
452 { "OPERAND_TYPE_REGBND",
454 { "OPERAND_TYPE_ESSEG",
456 { "OPERAND_TYPE_ACC8",
458 { "OPERAND_TYPE_ACC16",
460 { "OPERAND_TYPE_ACC32",
462 { "OPERAND_TYPE_ACC64",
464 { "OPERAND_TYPE_DISP16_32",
466 { "OPERAND_TYPE_ANYDISP",
467 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
468 { "OPERAND_TYPE_IMM16_32",
470 { "OPERAND_TYPE_IMM16_32S",
472 { "OPERAND_TYPE_IMM16_32_32S",
473 "Imm16|Imm32|Imm32S" },
474 { "OPERAND_TYPE_IMM32_64",
476 { "OPERAND_TYPE_IMM32_32S_DISP32",
477 "Imm32|Imm32S|Disp32" },
478 { "OPERAND_TYPE_IMM64_DISP64",
480 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
481 "Imm32|Imm32S|Imm64|Disp32" },
482 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
483 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
484 { "OPERAND_TYPE_ANYIMM",
485 "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
488 typedef struct bitfield
495 #define BITFIELD(n) { n, 0, #n }
497 static bitfield cpu_flags
[] =
507 BITFIELD (CpuClflush
),
509 BITFIELD (CpuSYSCALL
),
514 BITFIELD (CpuFISTTP
),
520 BITFIELD (CpuSSE4_1
),
521 BITFIELD (CpuSSE4_2
),
524 BITFIELD (CpuAVX512F
),
525 BITFIELD (CpuAVX512CD
),
526 BITFIELD (CpuAVX512ER
),
527 BITFIELD (CpuAVX512PF
),
528 BITFIELD (CpuAVX512VL
),
529 BITFIELD (CpuAVX512DQ
),
530 BITFIELD (CpuAVX512BW
),
536 BITFIELD (Cpu3dnowA
),
537 BITFIELD (CpuPadLock
),
543 BITFIELD (CpuXsaveopt
),
545 BITFIELD (CpuPCLMUL
),
556 BITFIELD (CpuRdtscp
),
557 BITFIELD (CpuFSGSBase
),
564 BITFIELD (CpuINVPCID
),
565 BITFIELD (CpuVMFUNC
),
566 BITFIELD (CpuRDSEED
),
568 BITFIELD (CpuPRFCHW
),
571 BITFIELD (CpuClflushOpt
),
572 BITFIELD (CpuXSAVES
),
573 BITFIELD (CpuXSAVEC
),
574 BITFIELD (CpuPREFETCHWT1
),
580 BITFIELD (CpuAVX512IFMA
),
581 BITFIELD (CpuAVX512VBMI
),
582 BITFIELD (CpuAVX512_4FMAPS
),
583 BITFIELD (CpuAVX512_4VNNIW
),
584 BITFIELD (CpuAVX512_VPOPCNTDQ
),
585 BITFIELD (CpuAVX512_VBMI2
),
586 BITFIELD (CpuAVX512_VNNI
),
587 BITFIELD (CpuAVX512_BITALG
),
588 BITFIELD (CpuAVX512_BF16
),
589 BITFIELD (CpuAVX512_VP2INTERSECT
),
590 BITFIELD (CpuMWAITX
),
591 BITFIELD (CpuCLZERO
),
594 BITFIELD (CpuPTWRITE
),
599 BITFIELD (CpuVPCLMULQDQ
),
600 BITFIELD (CpuWBNOINVD
),
601 BITFIELD (CpuPCONFIG
),
602 BITFIELD (CpuWAITPKG
),
603 BITFIELD (CpuCLDEMOTE
),
604 BITFIELD (CpuMOVDIRI
),
605 BITFIELD (CpuMOVDIR64B
),
606 BITFIELD (CpuENQCMD
),
608 BITFIELD (CpuMCOMMIT
),
610 BITFIELD (CpuUnused
),
614 static bitfield opcode_modifiers
[] =
620 BITFIELD (ShortForm
),
622 BITFIELD (JumpDword
),
624 BITFIELD (JumpInterSegment
),
628 BITFIELD (CheckRegSize
),
629 BITFIELD (IgnoreSize
),
630 BITFIELD (DefaultSize
),
640 BITFIELD (BNDPrefixOk
),
641 BITFIELD (NoTrackPrefixOk
),
642 BITFIELD (IsLockable
),
643 BITFIELD (RegKludge
),
644 BITFIELD (Implicit1stXmm0
),
645 BITFIELD (RepPrefixOk
),
646 BITFIELD (HLEPrefixOk
),
649 BITFIELD (AddrPrefixOpReg
),
658 BITFIELD (VexOpcode
),
659 BITFIELD (VexSources
),
665 BITFIELD (Broadcast
),
666 BITFIELD (StaticRounding
),
668 BITFIELD (Disp8MemShift
),
669 BITFIELD (NoDefMask
),
670 BITFIELD (ImplicitQuadGroup
),
672 BITFIELD (ATTMnemonic
),
673 BITFIELD (ATTSyntax
),
674 BITFIELD (IntelSyntax
),
679 #define CLASS(n) #n, n
681 static const struct {
683 enum operand_class value
;
684 } operand_classes
[] = {
698 static bitfield operand_types
[] =
707 BITFIELD (BaseIndex
),
713 BITFIELD (InOutPortReg
),
714 BITFIELD (ShiftCount
),
716 BITFIELD (JumpAbsolute
),
727 BITFIELD (Unspecified
),
734 static const char *filename
;
735 static i386_cpu_flags active_cpu_flags
;
736 static int active_isstring
;
739 compare (const void *x
, const void *y
)
741 const bitfield
*xp
= (const bitfield
*) x
;
742 const bitfield
*yp
= (const bitfield
*) y
;
743 return xp
->position
- yp
->position
;
747 fail (const char *message
, ...)
751 va_start (args
, message
);
752 fprintf (stderr
, _("%s: error: "), program_name
);
753 vfprintf (stderr
, message
, args
);
759 process_copyright (FILE *fp
)
761 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
762 /* Copyright (C) 2007-2019 Free Software Foundation, Inc.\n\
764 This file is part of the GNU opcodes library.\n\
766 This library is free software; you can redistribute it and/or modify\n\
767 it under the terms of the GNU General Public License as published by\n\
768 the Free Software Foundation; either version 3, or (at your option)\n\
769 any later version.\n\
771 It is distributed in the hope that it will be useful, but WITHOUT\n\
772 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
773 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
774 License for more details.\n\
776 You should have received a copy of the GNU General Public License\n\
777 along with this program; if not, write to the Free Software\n\
778 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
779 MA 02110-1301, USA. */\n");
782 /* Remove leading white spaces. */
785 remove_leading_whitespaces (char *str
)
787 while (ISSPACE (*str
))
792 /* Remove trailing white spaces. */
795 remove_trailing_whitespaces (char *str
)
797 size_t last
= strlen (str
);
805 if (ISSPACE (str
[last
]))
813 /* Find next field separated by SEP and terminate it. Return a
814 pointer to the one after it. */
817 next_field (char *str
, char sep
, char **next
, char *last
)
821 p
= remove_leading_whitespaces (str
);
822 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
825 remove_trailing_whitespaces (p
);
835 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
838 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
841 char *str
, *next
, *last
;
844 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
845 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
847 /* Turn on selective bits. */
848 char *init
= xstrdup (cpu_flag_init
[i
].init
);
849 last
= init
+ strlen (init
);
850 for (next
= init
; next
&& next
< last
; )
852 str
= next_field (next
, '|', &next
, last
);
854 set_bitfield (str
, array
, 1, size
, lineno
);
864 set_bitfield (char *f
, bitfield
*array
, int value
,
865 unsigned int size
, int lineno
)
869 if (strcmp (f
, "CpuFP") == 0)
871 set_bitfield("Cpu387", array
, value
, size
, lineno
);
872 set_bitfield("Cpu287", array
, value
, size
, lineno
);
875 else if (strcmp (f
, "Mmword") == 0)
877 else if (strcmp (f
, "Oword") == 0)
880 for (i
= 0; i
< size
; i
++)
881 if (strcasecmp (array
[i
].name
, f
) == 0)
883 array
[i
].value
= value
;
889 const char *v
= strchr (f
, '=');
896 for (i
= 0; i
< size
; i
++)
897 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
899 value
= strtol (v
+ 1, &end
, 0);
902 array
[i
].value
= value
;
910 /* Handle CPU_XXX_FLAGS. */
911 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
915 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
917 fail (_("unknown bitfield: %s\n"), f
);
921 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
922 int macro
, const char *comma
, const char *indent
)
926 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
928 fprintf (table
, "%s{ { ", indent
);
930 for (i
= 0; i
< size
- 1; i
++)
932 if (((i
+ 1) % 20) != 0)
933 fprintf (table
, "%d, ", flags
[i
].value
);
935 fprintf (table
, "%d,", flags
[i
].value
);
936 if (((i
+ 1) % 20) == 0)
938 /* We need \\ for macro. */
940 fprintf (table
, " \\\n %s", indent
);
942 fprintf (table
, "\n %s", indent
);
945 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
948 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
952 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
953 const char *comma
, const char *indent
,
956 char *str
, *next
, *last
;
958 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
960 /* Copy the default cpu flags. */
961 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
963 if (strcasecmp (flag
, "unknown") == 0)
965 /* We turn on everything except for cpu64 in case of
966 CPU_UNKNOWN_FLAGS. */
967 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
968 if (flags
[i
].position
!= Cpu64
)
971 else if (flag
[0] == '~')
973 last
= flag
+ strlen (flag
);
980 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
987 /* First we turn on everything except for cpu64. */
988 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
989 if (flags
[i
].position
!= Cpu64
)
992 /* Turn off selective bits. */
993 for (; next
&& next
< last
; )
995 str
= next_field (next
, '|', &next
, last
);
997 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
1000 else if (strcmp (flag
, "0"))
1002 /* Turn on selective bits. */
1003 last
= flag
+ strlen (flag
);
1004 for (next
= flag
; next
&& next
< last
; )
1006 str
= next_field (next
, '|', &next
, last
);
1008 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
1012 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1017 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1021 fprintf (table
, " { ");
1023 for (i
= 0; i
< size
- 1; i
++)
1025 if (((i
+ 1) % 20) != 0)
1026 fprintf (table
, "%d, ", modifier
[i
].value
);
1028 fprintf (table
, "%d,", modifier
[i
].value
);
1029 if (((i
+ 1) % 20) == 0)
1030 fprintf (table
, "\n ");
1033 fprintf (table
, "%d },\n", modifier
[i
].value
);
1037 adjust_broadcast_modifier (char **opnd
)
1039 char *str
, *next
, *last
, *op
;
1040 int bcst_type
= INT_MAX
;
1042 /* Skip the immediate operand. */
1044 if (strcasecmp(op
, "Imm8") == 0)
1048 last
= op
+ strlen (op
);
1049 for (next
= op
; next
&& next
< last
; )
1051 str
= next_field (next
, '|', &next
, last
);
1054 if (strcasecmp(str
, "Byte") == 0)
1056 /* The smalest broadcast type, no need to check
1058 bcst_type
= BYTE_BROADCAST
;
1061 else if (strcasecmp(str
, "Word") == 0)
1063 if (bcst_type
> WORD_BROADCAST
)
1064 bcst_type
= WORD_BROADCAST
;
1066 else if (strcasecmp(str
, "Dword") == 0)
1068 if (bcst_type
> DWORD_BROADCAST
)
1069 bcst_type
= DWORD_BROADCAST
;
1071 else if (strcasecmp(str
, "Qword") == 0)
1073 if (bcst_type
> QWORD_BROADCAST
)
1074 bcst_type
= QWORD_BROADCAST
;
1080 if (bcst_type
== INT_MAX
)
1081 fail (_("unknown broadcast operand: %s\n"), op
);
1087 process_i386_opcode_modifier (FILE *table
, char *mod
, char **opnd
, int lineno
)
1089 char *str
, *next
, *last
;
1090 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1092 active_isstring
= 0;
1094 /* Copy the default opcode modifier. */
1095 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1097 if (strcmp (mod
, "0"))
1099 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1101 last
= mod
+ strlen (mod
);
1102 for (next
= mod
; next
&& next
< last
; )
1104 str
= next_field (next
, '|', &next
, last
);
1108 if (strcasecmp(str
, "Broadcast") == 0)
1109 val
= adjust_broadcast_modifier (opnd
);
1110 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1112 if (strcasecmp(str
, "IsString") == 0)
1113 active_isstring
= 1;
1115 if (strcasecmp(str
, "W") == 0)
1118 if (strcasecmp(str
, "No_bSuf") == 0)
1120 if (strcasecmp(str
, "No_wSuf") == 0)
1122 if (strcasecmp(str
, "No_lSuf") == 0)
1124 if (strcasecmp(str
, "No_qSuf") == 0)
1129 if (have_w
&& !bwlq_suf
)
1130 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1131 if (have_w
&& !(bwlq_suf
& 1))
1132 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1134 if (have_w
&& !(bwlq_suf
& ~1))
1136 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1139 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1149 output_operand_type (FILE *table
, enum operand_class
class,
1150 const bitfield
*types
, unsigned int size
,
1151 enum stage stage
, const char *indent
)
1155 fprintf (table
, "{ { %d, ", class);
1157 for (i
= 0; i
< size
- 1; i
++)
1159 if (((i
+ 2) % 20) != 0)
1160 fprintf (table
, "%d, ", types
[i
].value
);
1162 fprintf (table
, "%d,", types
[i
].value
);
1163 if (((i
+ 2) % 20) == 0)
1165 /* We need \\ for macro. */
1166 if (stage
== stage_macros
)
1167 fprintf (table
, " \\\n%s", indent
);
1169 fprintf (table
, "\n%s", indent
);
1173 fprintf (table
, "%d } }", types
[i
].value
);
1177 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1178 const char *indent
, int lineno
)
1180 char *str
, *next
, *last
;
1181 enum operand_class
class = ClassNone
;
1182 bitfield types
[ARRAY_SIZE (operand_types
)];
1184 /* Copy the default operand type. */
1185 memcpy (types
, operand_types
, sizeof (types
));
1187 if (strcmp (op
, "0"))
1191 last
= op
+ strlen (op
);
1192 for (next
= op
; next
&& next
< last
; )
1194 str
= next_field (next
, '|', &next
, last
);
1199 if (!strncmp(str
, "Class=", 6))
1201 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1202 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1204 class = operand_classes
[i
].value
;
1212 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1213 if (strcasecmp(str
, "BaseIndex") == 0)
1218 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1220 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1221 if (!active_cpu_flags
.bitfield
.cpu64
1222 && !active_cpu_flags
.bitfield
.cpumpx
)
1223 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1224 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1225 if (!active_cpu_flags
.bitfield
.cpuno64
)
1226 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1229 output_operand_type (table
, class, types
, ARRAY_SIZE (types
), stage
,
1234 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1235 char *last
, int lineno
)
1238 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1239 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1241 /* Find number of operands. */
1242 operands
= next_field (str
, ',', &str
, last
);
1244 /* Find base_opcode. */
1245 base_opcode
= next_field (str
, ',', &str
, last
);
1247 /* Find extension_opcode. */
1248 extension_opcode
= next_field (str
, ',', &str
, last
);
1250 /* Find opcode_length. */
1251 opcode_length
= next_field (str
, ',', &str
, last
);
1253 /* Find cpu_flags. */
1254 cpu_flags
= next_field (str
, ',', &str
, last
);
1256 /* Find opcode_modifier. */
1257 opcode_modifier
= next_field (str
, ',', &str
, last
);
1259 /* Remove the first {. */
1260 str
= remove_leading_whitespaces (str
);
1263 str
= remove_leading_whitespaces (str
+ 1);
1267 /* There are at least "X}". */
1271 /* Remove trailing white spaces and }. */
1275 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1284 /* Find operand_types. */
1285 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1289 operand_types
[i
] = NULL
;
1293 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1294 if (*operand_types
[i
] == '0')
1297 operand_types
[i
] = NULL
;
1302 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1303 name
, base_opcode
, extension_opcode
, opcode_length
, operands
);
1305 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1307 process_i386_opcode_modifier (table
, opcode_modifier
, operand_types
, lineno
);
1309 fprintf (table
, " { ");
1311 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1313 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1316 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1322 fprintf (table
, ",\n ");
1324 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1327 fprintf (table
, " } },\n");
1330 struct opcode_hash_entry
1332 struct opcode_hash_entry
*next
;
1338 /* Calculate the hash value of an opcode hash entry P. */
1341 opcode_hash_hash (const void *p
)
1343 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1344 return htab_hash_string (entry
->name
);
1347 /* Compare a string Q against an opcode hash entry P. */
1350 opcode_hash_eq (const void *p
, const void *q
)
1352 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1353 const char *name
= (const char *) q
;
1354 return strcmp (name
, entry
->name
) == 0;
1358 process_i386_opcodes (FILE *table
)
1363 char *str
, *p
, *last
, *name
;
1364 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1365 htab_t opcode_hash_table
;
1366 struct opcode_hash_entry
**opcode_array
;
1367 unsigned int opcode_array_size
= 1024;
1368 int lineno
= 0, marker
= 0;
1370 filename
= "i386-opc.tbl";
1374 opcode_array
= (struct opcode_hash_entry
**)
1375 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1377 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1378 opcode_hash_eq
, NULL
,
1381 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1382 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1384 /* Put everything on opcode array. */
1387 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1392 p
= remove_leading_whitespaces (buf
);
1394 /* Skip comments. */
1395 str
= strstr (p
, "//");
1399 /* Remove trailing white spaces. */
1400 remove_trailing_whitespaces (p
);
1405 if (!strcmp("### MARKER ###", buf
))
1409 /* Since we ignore all included files (we only care about their
1410 #define-s here), we don't need to monitor filenames. The final
1411 line number directive is going to refer to the main source file
1416 p
= remove_leading_whitespaces (p
+ 1);
1417 if (!strncmp(p
, "line", 4))
1419 ln
= strtoul (p
, &end
, 10);
1420 if (ln
> 1 && ln
< INT_MAX
1421 && *remove_leading_whitespaces (end
) == '"')
1424 /* Ignore comments. */
1434 last
= p
+ strlen (p
);
1437 name
= next_field (p
, ',', &str
, last
);
1439 /* Get the slot in hash table. */
1440 hash_slot
= (struct opcode_hash_entry
**)
1441 htab_find_slot_with_hash (opcode_hash_table
, name
,
1442 htab_hash_string (name
),
1445 if (*hash_slot
== NULL
)
1447 /* It is the new one. Put it on opcode array. */
1448 if (i
>= opcode_array_size
)
1450 /* Grow the opcode array when needed. */
1451 opcode_array_size
+= 1024;
1452 opcode_array
= (struct opcode_hash_entry
**)
1453 xrealloc (opcode_array
,
1454 sizeof (*opcode_array
) * opcode_array_size
);
1457 opcode_array
[i
] = (struct opcode_hash_entry
*)
1458 xmalloc (sizeof (struct opcode_hash_entry
));
1459 opcode_array
[i
]->next
= NULL
;
1460 opcode_array
[i
]->name
= xstrdup (name
);
1461 opcode_array
[i
]->opcode
= xstrdup (str
);
1462 opcode_array
[i
]->lineno
= lineno
;
1463 *hash_slot
= opcode_array
[i
];
1468 /* Append it to the existing one. */
1470 while ((*entry
) != NULL
)
1471 entry
= &(*entry
)->next
;
1472 *entry
= (struct opcode_hash_entry
*)
1473 xmalloc (sizeof (struct opcode_hash_entry
));
1474 (*entry
)->next
= NULL
;
1475 (*entry
)->name
= (*hash_slot
)->name
;
1476 (*entry
)->opcode
= xstrdup (str
);
1477 (*entry
)->lineno
= lineno
;
1481 /* Process opcode array. */
1482 for (j
= 0; j
< i
; j
++)
1484 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1488 lineno
= next
->lineno
;
1489 last
= str
+ strlen (str
);
1490 output_i386_opcode (table
, name
, str
, last
, lineno
);
1496 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1498 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1500 process_i386_opcode_modifier (table
, "0", NULL
, -1);
1502 fprintf (table
, " { ");
1503 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1504 fprintf (table
, " } }\n");
1506 fprintf (table
, "};\n");
1510 process_i386_registers (FILE *table
)
1514 char *str
, *p
, *last
;
1515 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1516 char *dw2_32_num
, *dw2_64_num
;
1519 filename
= "i386-reg.tbl";
1520 fp
= fopen (filename
, "r");
1522 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1525 fprintf (table
, "\n/* i386 register table. */\n\n");
1526 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1530 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1535 p
= remove_leading_whitespaces (buf
);
1537 /* Skip comments. */
1538 str
= strstr (p
, "//");
1542 /* Remove trailing white spaces. */
1543 remove_trailing_whitespaces (p
);
1548 fprintf (table
, "%s\n", p
);
1556 last
= p
+ strlen (p
);
1558 /* Find reg_name. */
1559 reg_name
= next_field (p
, ',', &str
, last
);
1561 /* Find reg_type. */
1562 reg_type
= next_field (str
, ',', &str
, last
);
1564 /* Find reg_flags. */
1565 reg_flags
= next_field (str
, ',', &str
, last
);
1568 reg_num
= next_field (str
, ',', &str
, last
);
1570 fprintf (table
, " { \"%s\",\n ", reg_name
);
1572 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1575 /* Find 32-bit Dwarf2 register number. */
1576 dw2_32_num
= next_field (str
, ',', &str
, last
);
1578 /* Find 64-bit Dwarf2 register number. */
1579 dw2_64_num
= next_field (str
, ',', &str
, last
);
1581 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1582 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1587 fprintf (table
, "};\n");
1589 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1593 process_i386_initializers (void)
1596 FILE *fp
= fopen ("i386-init.h", "w");
1600 fail (_("can't create i386-init.h, errno = %s\n"),
1603 process_copyright (fp
);
1605 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1607 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1608 init
= xstrdup (cpu_flag_init
[i
].init
);
1609 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1613 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1615 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1616 init
= xstrdup (operand_type_init
[i
].init
);
1617 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1625 /* Program options. */
1626 #define OPTION_SRCDIR 200
1628 struct option long_options
[] =
1630 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1631 {"debug", no_argument
, NULL
, 'd'},
1632 {"version", no_argument
, NULL
, 'V'},
1633 {"help", no_argument
, NULL
, 'h'},
1634 {0, no_argument
, NULL
, 0}
1638 print_version (void)
1640 printf ("%s: version 1.0\n", program_name
);
1645 usage (FILE * stream
, int status
)
1647 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1653 main (int argc
, char **argv
)
1655 extern int chdir (char *);
1656 char *srcdir
= NULL
;
1658 unsigned int i
, cpumax
;
1661 program_name
= *argv
;
1662 xmalloc_set_program_name (program_name
);
1664 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1689 if (chdir (srcdir
) != 0)
1690 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1691 srcdir
, xstrerror (errno
));
1693 /* cpu_flags isn't sorted by position. */
1695 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1696 if (cpu_flags
[i
].position
> cpumax
)
1697 cpumax
= cpu_flags
[i
].position
;
1699 /* Check the unused bitfield in i386_cpu_flags. */
1701 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
1703 if ((cpumax
- 1) != CpuMax
)
1704 fail (_("CpuMax != %d!\n"), cpumax
);
1706 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
1708 if (cpumax
!= CpuMax
)
1709 fail (_("CpuMax != %d!\n"), cpumax
);
1711 c
= CpuNumOfBits
- CpuMax
- 1;
1713 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1716 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
1718 /* Check the unused bitfield in i386_operand_type. */
1720 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
== OTNum
+ 1);
1722 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
== OTNum
);
1724 c
= OTNumOfBits
- OTMax
- 1;
1726 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1729 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1732 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1733 sizeof (opcode_modifiers
[0]), compare
);
1735 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1736 sizeof (operand_types
[0]), compare
);
1738 table
= fopen ("i386-tbl.h", "w");
1740 fail (_("can't create i386-tbl.h, errno = %s\n"),
1743 process_copyright (table
);
1745 process_i386_opcodes (table
);
1746 process_i386_registers (table
);
1747 process_i386_initializers ();