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",
446 { "OPERAND_TYPE_REGYMM",
448 { "OPERAND_TYPE_REGZMM",
450 { "OPERAND_TYPE_REGMASK",
452 { "OPERAND_TYPE_ESSEG",
454 { "OPERAND_TYPE_ACC8",
456 { "OPERAND_TYPE_ACC16",
458 { "OPERAND_TYPE_ACC32",
460 { "OPERAND_TYPE_ACC64",
462 { "OPERAND_TYPE_DISP16_32",
464 { "OPERAND_TYPE_ANYDISP",
465 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
466 { "OPERAND_TYPE_IMM16_32",
468 { "OPERAND_TYPE_IMM16_32S",
470 { "OPERAND_TYPE_IMM16_32_32S",
471 "Imm16|Imm32|Imm32S" },
472 { "OPERAND_TYPE_IMM32_64",
474 { "OPERAND_TYPE_IMM32_32S_DISP32",
475 "Imm32|Imm32S|Disp32" },
476 { "OPERAND_TYPE_IMM64_DISP64",
478 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
479 "Imm32|Imm32S|Imm64|Disp32" },
480 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
481 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
482 { "OPERAND_TYPE_REGBND",
486 typedef struct bitfield
493 #define BITFIELD(n) { n, 0, #n }
495 static bitfield cpu_flags
[] =
505 BITFIELD (CpuClflush
),
507 BITFIELD (CpuSYSCALL
),
512 BITFIELD (CpuFISTTP
),
518 BITFIELD (CpuSSE4_1
),
519 BITFIELD (CpuSSE4_2
),
522 BITFIELD (CpuAVX512F
),
523 BITFIELD (CpuAVX512CD
),
524 BITFIELD (CpuAVX512ER
),
525 BITFIELD (CpuAVX512PF
),
526 BITFIELD (CpuAVX512VL
),
527 BITFIELD (CpuAVX512DQ
),
528 BITFIELD (CpuAVX512BW
),
534 BITFIELD (Cpu3dnowA
),
535 BITFIELD (CpuPadLock
),
541 BITFIELD (CpuXsaveopt
),
543 BITFIELD (CpuPCLMUL
),
554 BITFIELD (CpuRdtscp
),
555 BITFIELD (CpuFSGSBase
),
562 BITFIELD (CpuINVPCID
),
563 BITFIELD (CpuVMFUNC
),
564 BITFIELD (CpuRDSEED
),
566 BITFIELD (CpuPRFCHW
),
569 BITFIELD (CpuClflushOpt
),
570 BITFIELD (CpuXSAVES
),
571 BITFIELD (CpuXSAVEC
),
572 BITFIELD (CpuPREFETCHWT1
),
578 BITFIELD (CpuAVX512IFMA
),
579 BITFIELD (CpuAVX512VBMI
),
580 BITFIELD (CpuAVX512_4FMAPS
),
581 BITFIELD (CpuAVX512_4VNNIW
),
582 BITFIELD (CpuAVX512_VPOPCNTDQ
),
583 BITFIELD (CpuAVX512_VBMI2
),
584 BITFIELD (CpuAVX512_VNNI
),
585 BITFIELD (CpuAVX512_BITALG
),
586 BITFIELD (CpuAVX512_BF16
),
587 BITFIELD (CpuAVX512_VP2INTERSECT
),
588 BITFIELD (CpuMWAITX
),
589 BITFIELD (CpuCLZERO
),
592 BITFIELD (CpuPTWRITE
),
597 BITFIELD (CpuVPCLMULQDQ
),
598 BITFIELD (CpuWBNOINVD
),
599 BITFIELD (CpuPCONFIG
),
600 BITFIELD (CpuWAITPKG
),
601 BITFIELD (CpuCLDEMOTE
),
602 BITFIELD (CpuMOVDIRI
),
603 BITFIELD (CpuMOVDIR64B
),
604 BITFIELD (CpuENQCMD
),
606 BITFIELD (CpuMCOMMIT
),
608 BITFIELD (CpuUnused
),
612 static bitfield opcode_modifiers
[] =
618 BITFIELD (ShortForm
),
620 BITFIELD (JumpDword
),
622 BITFIELD (JumpInterSegment
),
626 BITFIELD (CheckRegSize
),
627 BITFIELD (IgnoreSize
),
628 BITFIELD (DefaultSize
),
638 BITFIELD (BNDPrefixOk
),
639 BITFIELD (NoTrackPrefixOk
),
640 BITFIELD (IsLockable
),
641 BITFIELD (RegKludge
),
642 BITFIELD (Implicit1stXmm0
),
643 BITFIELD (RepPrefixOk
),
644 BITFIELD (HLEPrefixOk
),
647 BITFIELD (AddrPrefixOpReg
),
656 BITFIELD (VexOpcode
),
657 BITFIELD (VexSources
),
663 BITFIELD (Broadcast
),
664 BITFIELD (StaticRounding
),
666 BITFIELD (Disp8MemShift
),
667 BITFIELD (NoDefMask
),
668 BITFIELD (ImplicitQuadGroup
),
670 BITFIELD (ATTMnemonic
),
671 BITFIELD (ATTSyntax
),
672 BITFIELD (IntelSyntax
),
677 static bitfield operand_types
[] =
690 BITFIELD (BaseIndex
),
696 BITFIELD (InOutPortReg
),
697 BITFIELD (ShiftCount
),
703 BITFIELD (JumpAbsolute
),
714 BITFIELD (Unspecified
),
722 static const char *filename
;
723 static i386_cpu_flags active_cpu_flags
;
724 static int active_isstring
;
727 compare (const void *x
, const void *y
)
729 const bitfield
*xp
= (const bitfield
*) x
;
730 const bitfield
*yp
= (const bitfield
*) y
;
731 return xp
->position
- yp
->position
;
735 fail (const char *message
, ...)
739 va_start (args
, message
);
740 fprintf (stderr
, _("%s: error: "), program_name
);
741 vfprintf (stderr
, message
, args
);
747 process_copyright (FILE *fp
)
749 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
750 /* Copyright (C) 2007-2019 Free Software Foundation, Inc.\n\
752 This file is part of the GNU opcodes library.\n\
754 This library is free software; you can redistribute it and/or modify\n\
755 it under the terms of the GNU General Public License as published by\n\
756 the Free Software Foundation; either version 3, or (at your option)\n\
757 any later version.\n\
759 It is distributed in the hope that it will be useful, but WITHOUT\n\
760 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
761 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
762 License for more details.\n\
764 You should have received a copy of the GNU General Public License\n\
765 along with this program; if not, write to the Free Software\n\
766 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
767 MA 02110-1301, USA. */\n");
770 /* Remove leading white spaces. */
773 remove_leading_whitespaces (char *str
)
775 while (ISSPACE (*str
))
780 /* Remove trailing white spaces. */
783 remove_trailing_whitespaces (char *str
)
785 size_t last
= strlen (str
);
793 if (ISSPACE (str
[last
]))
801 /* Find next field separated by SEP and terminate it. Return a
802 pointer to the one after it. */
805 next_field (char *str
, char sep
, char **next
, char *last
)
809 p
= remove_leading_whitespaces (str
);
810 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
813 remove_trailing_whitespaces (p
);
823 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
826 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
829 char *str
, *next
, *last
;
832 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
833 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
835 /* Turn on selective bits. */
836 char *init
= xstrdup (cpu_flag_init
[i
].init
);
837 last
= init
+ strlen (init
);
838 for (next
= init
; next
&& next
< last
; )
840 str
= next_field (next
, '|', &next
, last
);
842 set_bitfield (str
, array
, 1, size
, lineno
);
852 set_bitfield (char *f
, bitfield
*array
, int value
,
853 unsigned int size
, int lineno
)
857 if (strcmp (f
, "CpuFP") == 0)
859 set_bitfield("Cpu387", array
, value
, size
, lineno
);
860 set_bitfield("Cpu287", array
, value
, size
, lineno
);
863 else if (strcmp (f
, "Mmword") == 0)
865 else if (strcmp (f
, "Oword") == 0)
868 for (i
= 0; i
< size
; i
++)
869 if (strcasecmp (array
[i
].name
, f
) == 0)
871 array
[i
].value
= value
;
877 const char *v
= strchr (f
, '=');
884 for (i
= 0; i
< size
; i
++)
885 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
887 value
= strtol (v
+ 1, &end
, 0);
890 array
[i
].value
= value
;
898 /* Handle CPU_XXX_FLAGS. */
899 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
903 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
905 fail (_("unknown bitfield: %s\n"), f
);
909 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
910 int macro
, const char *comma
, const char *indent
)
914 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
916 fprintf (table
, "%s{ { ", indent
);
918 for (i
= 0; i
< size
- 1; i
++)
920 if (((i
+ 1) % 20) != 0)
921 fprintf (table
, "%d, ", flags
[i
].value
);
923 fprintf (table
, "%d,", flags
[i
].value
);
924 if (((i
+ 1) % 20) == 0)
926 /* We need \\ for macro. */
928 fprintf (table
, " \\\n %s", indent
);
930 fprintf (table
, "\n %s", indent
);
933 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
936 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
940 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
941 const char *comma
, const char *indent
,
944 char *str
, *next
, *last
;
946 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
948 /* Copy the default cpu flags. */
949 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
951 if (strcasecmp (flag
, "unknown") == 0)
953 /* We turn on everything except for cpu64 in case of
954 CPU_UNKNOWN_FLAGS. */
955 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
956 if (flags
[i
].position
!= Cpu64
)
959 else if (flag
[0] == '~')
961 last
= flag
+ strlen (flag
);
968 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
975 /* First we turn on everything except for cpu64. */
976 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
977 if (flags
[i
].position
!= Cpu64
)
980 /* Turn off selective bits. */
981 for (; next
&& next
< last
; )
983 str
= next_field (next
, '|', &next
, last
);
985 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
988 else if (strcmp (flag
, "0"))
990 /* Turn on selective bits. */
991 last
= flag
+ strlen (flag
);
992 for (next
= flag
; next
&& next
< last
; )
994 str
= next_field (next
, '|', &next
, last
);
996 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
1000 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1005 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1009 fprintf (table
, " { ");
1011 for (i
= 0; i
< size
- 1; i
++)
1013 if (((i
+ 1) % 20) != 0)
1014 fprintf (table
, "%d, ", modifier
[i
].value
);
1016 fprintf (table
, "%d,", modifier
[i
].value
);
1017 if (((i
+ 1) % 20) == 0)
1018 fprintf (table
, "\n ");
1021 fprintf (table
, "%d },\n", modifier
[i
].value
);
1025 adjust_broadcast_modifier (char **opnd
)
1027 char *str
, *next
, *last
, *op
;
1028 int bcst_type
= INT_MAX
;
1030 /* Skip the immediate operand. */
1032 if (strcasecmp(op
, "Imm8") == 0)
1036 last
= op
+ strlen (op
);
1037 for (next
= op
; next
&& next
< last
; )
1039 str
= next_field (next
, '|', &next
, last
);
1042 if (strcasecmp(str
, "Byte") == 0)
1044 /* The smalest broadcast type, no need to check
1046 bcst_type
= BYTE_BROADCAST
;
1049 else if (strcasecmp(str
, "Word") == 0)
1051 if (bcst_type
> WORD_BROADCAST
)
1052 bcst_type
= WORD_BROADCAST
;
1054 else if (strcasecmp(str
, "Dword") == 0)
1056 if (bcst_type
> DWORD_BROADCAST
)
1057 bcst_type
= DWORD_BROADCAST
;
1059 else if (strcasecmp(str
, "Qword") == 0)
1061 if (bcst_type
> QWORD_BROADCAST
)
1062 bcst_type
= QWORD_BROADCAST
;
1068 if (bcst_type
== INT_MAX
)
1069 fail (_("unknown broadcast operand: %s\n"), op
);
1075 process_i386_opcode_modifier (FILE *table
, char *mod
, char **opnd
, int lineno
)
1077 char *str
, *next
, *last
;
1078 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1080 active_isstring
= 0;
1082 /* Copy the default opcode modifier. */
1083 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1085 if (strcmp (mod
, "0"))
1087 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1089 last
= mod
+ strlen (mod
);
1090 for (next
= mod
; next
&& next
< last
; )
1092 str
= next_field (next
, '|', &next
, last
);
1096 if (strcasecmp(str
, "Broadcast") == 0)
1097 val
= adjust_broadcast_modifier (opnd
);
1098 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1100 if (strcasecmp(str
, "IsString") == 0)
1101 active_isstring
= 1;
1103 if (strcasecmp(str
, "W") == 0)
1106 if (strcasecmp(str
, "No_bSuf") == 0)
1108 if (strcasecmp(str
, "No_wSuf") == 0)
1110 if (strcasecmp(str
, "No_lSuf") == 0)
1112 if (strcasecmp(str
, "No_qSuf") == 0)
1117 if (have_w
&& !bwlq_suf
)
1118 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1119 if (have_w
&& !(bwlq_suf
& 1))
1120 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1122 if (have_w
&& !(bwlq_suf
& ~1))
1124 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1127 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1137 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
1138 enum stage stage
, const char *indent
)
1142 fprintf (table
, "{ { ");
1144 for (i
= 0; i
< size
- 1; i
++)
1146 if (((i
+ 1) % 20) != 0)
1147 fprintf (table
, "%d, ", types
[i
].value
);
1149 fprintf (table
, "%d,", types
[i
].value
);
1150 if (((i
+ 1) % 20) == 0)
1152 /* We need \\ for macro. */
1153 if (stage
== stage_macros
)
1154 fprintf (table
, " \\\n%s", indent
);
1156 fprintf (table
, "\n%s", indent
);
1160 fprintf (table
, "%d } }", types
[i
].value
);
1164 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1165 const char *indent
, int lineno
)
1167 char *str
, *next
, *last
;
1168 bitfield types
[ARRAY_SIZE (operand_types
)];
1170 /* Copy the default operand type. */
1171 memcpy (types
, operand_types
, sizeof (types
));
1173 if (strcmp (op
, "0"))
1177 last
= op
+ strlen (op
);
1178 for (next
= op
; next
&& next
< last
; )
1180 str
= next_field (next
, '|', &next
, last
);
1183 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1184 if (strcasecmp(str
, "BaseIndex") == 0)
1189 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1191 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1192 if (!active_cpu_flags
.bitfield
.cpu64
1193 && !active_cpu_flags
.bitfield
.cpumpx
)
1194 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1195 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1196 if (!active_cpu_flags
.bitfield
.cpuno64
)
1197 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1200 output_operand_type (table
, types
, ARRAY_SIZE (types
), stage
,
1205 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1206 char *last
, int lineno
)
1209 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1210 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1212 /* Find number of operands. */
1213 operands
= next_field (str
, ',', &str
, last
);
1215 /* Find base_opcode. */
1216 base_opcode
= next_field (str
, ',', &str
, last
);
1218 /* Find extension_opcode. */
1219 extension_opcode
= next_field (str
, ',', &str
, last
);
1221 /* Find opcode_length. */
1222 opcode_length
= next_field (str
, ',', &str
, last
);
1224 /* Find cpu_flags. */
1225 cpu_flags
= next_field (str
, ',', &str
, last
);
1227 /* Find opcode_modifier. */
1228 opcode_modifier
= next_field (str
, ',', &str
, last
);
1230 /* Remove the first {. */
1231 str
= remove_leading_whitespaces (str
);
1234 str
= remove_leading_whitespaces (str
+ 1);
1238 /* There are at least "X}". */
1242 /* Remove trailing white spaces and }. */
1246 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1255 /* Find operand_types. */
1256 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1260 operand_types
[i
] = NULL
;
1264 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1265 if (*operand_types
[i
] == '0')
1268 operand_types
[i
] = NULL
;
1273 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1274 name
, base_opcode
, extension_opcode
, opcode_length
, operands
);
1276 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1278 process_i386_opcode_modifier (table
, opcode_modifier
, operand_types
, lineno
);
1280 fprintf (table
, " { ");
1282 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1284 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1287 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1293 fprintf (table
, ",\n ");
1295 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1298 fprintf (table
, " } },\n");
1301 struct opcode_hash_entry
1303 struct opcode_hash_entry
*next
;
1309 /* Calculate the hash value of an opcode hash entry P. */
1312 opcode_hash_hash (const void *p
)
1314 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1315 return htab_hash_string (entry
->name
);
1318 /* Compare a string Q against an opcode hash entry P. */
1321 opcode_hash_eq (const void *p
, const void *q
)
1323 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1324 const char *name
= (const char *) q
;
1325 return strcmp (name
, entry
->name
) == 0;
1329 process_i386_opcodes (FILE *table
)
1334 char *str
, *p
, *last
, *name
;
1335 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1336 htab_t opcode_hash_table
;
1337 struct opcode_hash_entry
**opcode_array
;
1338 unsigned int opcode_array_size
= 1024;
1339 int lineno
= 0, marker
= 0;
1341 filename
= "i386-opc.tbl";
1345 opcode_array
= (struct opcode_hash_entry
**)
1346 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1348 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1349 opcode_hash_eq
, NULL
,
1352 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1353 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1355 /* Put everything on opcode array. */
1358 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1363 p
= remove_leading_whitespaces (buf
);
1365 /* Skip comments. */
1366 str
= strstr (p
, "//");
1370 /* Remove trailing white spaces. */
1371 remove_trailing_whitespaces (p
);
1376 if (!strcmp("### MARKER ###", buf
))
1380 /* Since we ignore all included files (we only care about their
1381 #define-s here), we don't need to monitor filenames. The final
1382 line number directive is going to refer to the main source file
1387 p
= remove_leading_whitespaces (p
+ 1);
1388 if (!strncmp(p
, "line", 4))
1390 ln
= strtoul (p
, &end
, 10);
1391 if (ln
> 1 && ln
< INT_MAX
1392 && *remove_leading_whitespaces (end
) == '"')
1395 /* Ignore comments. */
1405 last
= p
+ strlen (p
);
1408 name
= next_field (p
, ',', &str
, last
);
1410 /* Get the slot in hash table. */
1411 hash_slot
= (struct opcode_hash_entry
**)
1412 htab_find_slot_with_hash (opcode_hash_table
, name
,
1413 htab_hash_string (name
),
1416 if (*hash_slot
== NULL
)
1418 /* It is the new one. Put it on opcode array. */
1419 if (i
>= opcode_array_size
)
1421 /* Grow the opcode array when needed. */
1422 opcode_array_size
+= 1024;
1423 opcode_array
= (struct opcode_hash_entry
**)
1424 xrealloc (opcode_array
,
1425 sizeof (*opcode_array
) * opcode_array_size
);
1428 opcode_array
[i
] = (struct opcode_hash_entry
*)
1429 xmalloc (sizeof (struct opcode_hash_entry
));
1430 opcode_array
[i
]->next
= NULL
;
1431 opcode_array
[i
]->name
= xstrdup (name
);
1432 opcode_array
[i
]->opcode
= xstrdup (str
);
1433 opcode_array
[i
]->lineno
= lineno
;
1434 *hash_slot
= opcode_array
[i
];
1439 /* Append it to the existing one. */
1441 while ((*entry
) != NULL
)
1442 entry
= &(*entry
)->next
;
1443 *entry
= (struct opcode_hash_entry
*)
1444 xmalloc (sizeof (struct opcode_hash_entry
));
1445 (*entry
)->next
= NULL
;
1446 (*entry
)->name
= (*hash_slot
)->name
;
1447 (*entry
)->opcode
= xstrdup (str
);
1448 (*entry
)->lineno
= lineno
;
1452 /* Process opcode array. */
1453 for (j
= 0; j
< i
; j
++)
1455 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1459 lineno
= next
->lineno
;
1460 last
= str
+ strlen (str
);
1461 output_i386_opcode (table
, name
, str
, last
, lineno
);
1467 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1469 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1471 process_i386_opcode_modifier (table
, "0", NULL
, -1);
1473 fprintf (table
, " { ");
1474 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1475 fprintf (table
, " } }\n");
1477 fprintf (table
, "};\n");
1481 process_i386_registers (FILE *table
)
1485 char *str
, *p
, *last
;
1486 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1487 char *dw2_32_num
, *dw2_64_num
;
1490 filename
= "i386-reg.tbl";
1491 fp
= fopen (filename
, "r");
1493 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1496 fprintf (table
, "\n/* i386 register table. */\n\n");
1497 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1501 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1506 p
= remove_leading_whitespaces (buf
);
1508 /* Skip comments. */
1509 str
= strstr (p
, "//");
1513 /* Remove trailing white spaces. */
1514 remove_trailing_whitespaces (p
);
1519 fprintf (table
, "%s\n", p
);
1527 last
= p
+ strlen (p
);
1529 /* Find reg_name. */
1530 reg_name
= next_field (p
, ',', &str
, last
);
1532 /* Find reg_type. */
1533 reg_type
= next_field (str
, ',', &str
, last
);
1535 /* Find reg_flags. */
1536 reg_flags
= next_field (str
, ',', &str
, last
);
1539 reg_num
= next_field (str
, ',', &str
, last
);
1541 fprintf (table
, " { \"%s\",\n ", reg_name
);
1543 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1546 /* Find 32-bit Dwarf2 register number. */
1547 dw2_32_num
= next_field (str
, ',', &str
, last
);
1549 /* Find 64-bit Dwarf2 register number. */
1550 dw2_64_num
= next_field (str
, ',', &str
, last
);
1552 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1553 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1558 fprintf (table
, "};\n");
1560 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1564 process_i386_initializers (void)
1567 FILE *fp
= fopen ("i386-init.h", "w");
1571 fail (_("can't create i386-init.h, errno = %s\n"),
1574 process_copyright (fp
);
1576 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1578 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1579 init
= xstrdup (cpu_flag_init
[i
].init
);
1580 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1584 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1586 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1587 init
= xstrdup (operand_type_init
[i
].init
);
1588 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1596 /* Program options. */
1597 #define OPTION_SRCDIR 200
1599 struct option long_options
[] =
1601 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1602 {"debug", no_argument
, NULL
, 'd'},
1603 {"version", no_argument
, NULL
, 'V'},
1604 {"help", no_argument
, NULL
, 'h'},
1605 {0, no_argument
, NULL
, 0}
1609 print_version (void)
1611 printf ("%s: version 1.0\n", program_name
);
1616 usage (FILE * stream
, int status
)
1618 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1624 main (int argc
, char **argv
)
1626 extern int chdir (char *);
1627 char *srcdir
= NULL
;
1629 unsigned int i
, cpumax
;
1632 program_name
= *argv
;
1633 xmalloc_set_program_name (program_name
);
1635 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1660 if (chdir (srcdir
) != 0)
1661 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1662 srcdir
, xstrerror (errno
));
1664 /* cpu_flags isn't sorted by position. */
1666 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1667 if (cpu_flags
[i
].position
> cpumax
)
1668 cpumax
= cpu_flags
[i
].position
;
1670 /* Check the unused bitfield in i386_cpu_flags. */
1672 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
1674 if ((cpumax
- 1) != CpuMax
)
1675 fail (_("CpuMax != %d!\n"), cpumax
);
1677 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
1679 if (cpumax
!= CpuMax
)
1680 fail (_("CpuMax != %d!\n"), cpumax
);
1682 c
= CpuNumOfBits
- CpuMax
- 1;
1684 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1687 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
1689 /* Check the unused bitfield in i386_operand_type. */
1691 static_assert (ARRAY_SIZE (operand_types
) == OTNum
+ 1);
1693 static_assert (ARRAY_SIZE (operand_types
) == OTNum
);
1695 c
= OTNumOfBits
- OTMax
- 1;
1697 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1700 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1703 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1704 sizeof (opcode_modifiers
[0]), compare
);
1706 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1707 sizeof (operand_types
[0]), compare
);
1709 table
= fopen ("i386-tbl.h", "w");
1711 fail (_("can't create i386-tbl.h, errno = %s\n"),
1714 process_copyright (table
);
1716 process_i386_opcodes (table
);
1717 process_i386_registers (table
);
1718 process_i386_initializers ();