1 /* Copyright (C) 2007-2022 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",
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|CpuLZCNT|CpuPOPCNT" },
95 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuLZCNT|CpuPOPCNT|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|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|CpuLZCNT|CpuPOPCNT|CpuSVME|CpuAES|CpuPCLMUL|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_ZNVER3_FLAGS",
107 "CPU_ZNVER2_FLAGS|CpuINVLPGB|CpuTLBSYNC|CpuVAES|CpuVPCLMULQDQ|CpuINVPCID|CpuSNP|CpuOSPKE" },
108 { "CPU_ZNVER4_FLAGS",
109 "CPU_ZNVER3_FLAGS|CpuAVX512F|CpuAVX512DQ|CpuAVX512IFMA|CpuAVX512CD|CpuAVX512BW|CpuAVX512VL|CpuAVX512_BF16|CpuAVX512VBMI|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_VPOPCNTDQ|CpuGFNI|CpuRMPQUERY" },
110 { "CPU_BTVER1_FLAGS",
111 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME" },
112 { "CPU_BTVER2_FLAGS",
113 "CPU_BTVER1_FLAGS|CPU_AVX_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuMovbe|CpuXsaveopt|CpuPRFCHW" },
121 "CPU_387_FLAGS|Cpu687" },
126 { "CPU_CLFLUSH_FLAGS",
130 { "CPU_SYSCALL_FLAGS",
137 "CPU_SSE_FLAGS|CpuSSE2" },
139 "CPU_SSE2_FLAGS|CpuSSE3" },
141 "CPU_SSE3_FLAGS|CpuSSSE3" },
142 { "CPU_SSE4_1_FLAGS",
143 "CPU_SSSE3_FLAGS|CpuSSE4_1" },
144 { "CPU_SSE4_2_FLAGS",
145 "CPU_SSE4_1_FLAGS|CpuSSE4_2|CpuPOPCNT" },
152 { "CPU_XSAVEOPT_FLAGS",
153 "CPU_XSAVE_FLAGS|CpuXsaveopt" },
155 "CPU_SSE2_FLAGS|CpuAES" },
156 { "CPU_PCLMUL_FLAGS",
157 "CPU_SSE2_FLAGS|CpuPCLMUL" },
159 "CPU_AVX_FLAGS|CpuFMA" },
161 "CPU_AVX_FLAGS|CpuFMA4" },
163 "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
165 "CPU_XSAVE_FLAGS|CpuLWP" },
174 { "CPU_RDTSCP_FLAGS",
178 { "CPU_FSGSBASE_FLAGS",
183 "CPU_AVX_FLAGS|CpuF16C" },
188 { "CPU_POPCNT_FLAGS",
194 { "CPU_INVPCID_FLAGS",
196 { "CPU_VMFUNC_FLAGS",
199 "CPU_MMX_FLAGS|Cpu3dnow" },
200 { "CPU_3DNOWA_FLAGS",
201 "CPU_3DNOW_FLAGS|Cpu3dnowA" },
202 { "CPU_PADLOCK_FLAGS",
207 "CPU_SSE3_FLAGS|CpuSSE4a" },
209 "CpuLZCNT|CpuPOPCNT" },
211 "CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
213 "CPU_AVX_FLAGS|CpuAVX2" },
214 { "CPU_AVX_VNNI_FLAGS",
215 "CPU_AVX2_FLAGS|CpuAVX_VNNI" },
216 { "CPU_AVX512F_FLAGS",
217 "CPU_AVX2_FLAGS|CpuAVX512F" },
218 { "CPU_AVX512CD_FLAGS",
219 "CPU_AVX512F_FLAGS|CpuAVX512CD" },
220 { "CPU_AVX512ER_FLAGS",
221 "CPU_AVX512F_FLAGS|CpuAVX512ER" },
222 { "CPU_AVX512PF_FLAGS",
223 "CPU_AVX512F_FLAGS|CpuAVX512PF" },
224 { "CPU_AVX512DQ_FLAGS",
225 "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
226 { "CPU_AVX512BW_FLAGS",
227 "CPU_AVX512F_FLAGS|CpuAVX512BW" },
228 { "CPU_AVX512VL_FLAGS",
229 "CPU_AVX512F_FLAGS|CpuAVX512VL" },
230 { "CPU_AVX512IFMA_FLAGS",
231 "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
232 { "CPU_AVX512VBMI_FLAGS",
233 "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
234 { "CPU_AVX512_4FMAPS_FLAGS",
235 "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
236 { "CPU_AVX512_4VNNIW_FLAGS",
237 "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
238 { "CPU_AVX512_VPOPCNTDQ_FLAGS",
239 "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
240 { "CPU_AVX512_VBMI2_FLAGS",
241 "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
242 { "CPU_AVX512_VNNI_FLAGS",
243 "CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
244 { "CPU_AVX512_BITALG_FLAGS",
245 "CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
246 { "CPU_AVX512_BF16_FLAGS",
247 "CPU_AVX512F_FLAGS|CpuAVX512_BF16" },
248 { "CPU_AVX512_FP16_FLAGS",
249 "CPU_AVX512BW_FLAGS|CpuAVX512_FP16" },
250 { "CPU_PREFETCHI_FLAGS",
252 { "CPU_AVX_IFMA_FLAGS",
253 "CPU_AVX2_FLAGS|CpuAVX_IFMA" },
254 { "CPU_AVX_VNNI_INT8_FLAGS",
255 "CPU_AVX2_FLAGS|CpuAVX_VNNI_INT8" },
256 { "CPU_CMPCCXADD_FLAGS",
258 { "CPU_WRMSRNS_FLAGS",
260 { "CPU_MSRLIST_FLAGS",
262 { "CPU_AVX_NE_CONVERT_FLAGS",
263 "CPU_AVX2_FLAGS|CpuAVX_NE_CONVERT" },
264 { "CPU_RAO_INT_FLAGS",
267 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
270 { "CPU_RDSEED_FLAGS",
272 { "CPU_PRFCHW_FLAGS",
277 "CPU_XSAVE_FLAGS|CpuMPX" },
279 "CPU_SSE2_FLAGS|CpuSHA" },
280 { "CPU_CLFLUSHOPT_FLAGS",
282 { "CPU_XSAVES_FLAGS",
283 "CPU_XSAVE_FLAGS|CpuXSAVES" },
284 { "CPU_XSAVEC_FLAGS",
285 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
286 { "CPU_PREFETCHWT1_FLAGS",
292 { "CPU_CLZERO_FLAGS",
294 { "CPU_MWAITX_FLAGS",
297 "CPU_XSAVE_FLAGS|CpuOSPKE" },
300 { "CPU_PTWRITE_FLAGS",
310 { "CPU_VPCLMULQDQ_FLAGS",
312 { "CPU_WBNOINVD_FLAGS",
314 { "CPU_PCONFIG_FLAGS",
316 { "CPU_WAITPKG_FLAGS",
320 { "CPU_CLDEMOTE_FLAGS",
322 { "CPU_AMX_INT8_FLAGS",
323 "CPU_AMX_TILE_FLAGS|CpuAMX_INT8" },
324 { "CPU_AMX_BF16_FLAGS",
325 "CPU_AMX_TILE_FLAGS|CpuAMX_BF16" },
326 { "CPU_AMX_FP16_FLAGS",
327 "CPU_AMX_TILE_FLAGS|CpuAMX_FP16" },
328 { "CPU_AMX_TILE_FLAGS",
330 { "CPU_MOVDIRI_FLAGS",
332 { "CPU_MOVDIR64B_FLAGS",
334 { "CPU_ENQCMD_FLAGS",
336 { "CPU_SERIALIZE_FLAGS",
338 { "CPU_AVX512_VP2INTERSECT_FLAGS",
339 "CpuAVX512_VP2INTERSECT" },
344 { "CPU_MCOMMIT_FLAGS",
346 { "CPU_SEV_ES_FLAGS",
348 { "CPU_TSXLDTRK_FLAGS",
352 { "CPU_WIDEKL_FLAGS",
354 { "CPU_HRESET_FLAGS",
356 { "CPU_INVLPGB_FLAGS",
358 { "CPU_TLBSYNC_FLAGS",
362 { "CPU_RMPQUERY_FLAGS",
364 { "CPU_ANY_X87_FLAGS",
365 "CPU_ANY_287_FLAGS|Cpu8087" },
366 { "CPU_ANY_287_FLAGS",
367 "CPU_ANY_387_FLAGS|Cpu287" },
368 { "CPU_ANY_387_FLAGS",
369 "CPU_ANY_687_FLAGS|Cpu387" },
370 { "CPU_ANY_687_FLAGS",
371 "Cpu687|CpuFISTTP" },
372 { "CPU_ANY_CMOV_FLAGS",
374 { "CPU_ANY_FXSR_FLAGS",
376 { "CPU_ANY_MMX_FLAGS",
377 "CPU_3DNOWA_FLAGS" },
378 { "CPU_ANY_SSE_FLAGS",
379 "CPU_ANY_SSE2_FLAGS|CpuSSE" },
380 { "CPU_ANY_SSE2_FLAGS",
381 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
382 { "CPU_ANY_SSE3_FLAGS",
383 "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
384 { "CPU_ANY_SSSE3_FLAGS",
385 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
386 { "CPU_ANY_SSE4_1_FLAGS",
387 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
388 { "CPU_ANY_SSE4_2_FLAGS",
390 { "CPU_ANY_SSE4A_FLAGS",
392 { "CPU_ANY_AVX_FLAGS",
393 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
394 { "CPU_ANY_AVX2_FLAGS",
395 "CPU_ANY_AVX512F_FLAGS|CpuAVX2|CpuAVX_VNNI|CpuAVX_IFMA|CpuAVX_VNNI_INT8|CpuAVX_NE_CONVERT" },
396 { "CPU_ANY_AVX512F_FLAGS",
397 "CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CPU_ANY_AVX512BW_FLAGS|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_BF16|CpuAVX512_VP2INTERSECT" },
398 { "CPU_ANY_AVX512CD_FLAGS",
400 { "CPU_ANY_AVX512ER_FLAGS",
402 { "CPU_ANY_AVX512PF_FLAGS",
404 { "CPU_ANY_AVX512DQ_FLAGS",
406 { "CPU_ANY_AVX512BW_FLAGS",
407 "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
408 { "CPU_ANY_AVX512VL_FLAGS",
410 { "CPU_ANY_AVX512IFMA_FLAGS",
412 { "CPU_ANY_AVX512VBMI_FLAGS",
414 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
415 "CpuAVX512_4FMAPS" },
416 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
417 "CpuAVX512_4VNNIW" },
418 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
419 "CpuAVX512_VPOPCNTDQ" },
420 { "CPU_ANY_IBT_FLAGS",
422 { "CPU_ANY_SHSTK_FLAGS",
424 { "CPU_ANY_AVX512_VBMI2_FLAGS",
426 { "CPU_ANY_AVX512_VNNI_FLAGS",
428 { "CPU_ANY_AVX512_BITALG_FLAGS",
429 "CpuAVX512_BITALG" },
430 { "CPU_ANY_AVX512_BF16_FLAGS",
432 { "CPU_ANY_AMX_INT8_FLAGS",
434 { "CPU_ANY_AMX_BF16_FLAGS",
436 { "CPU_ANY_AMX_TILE_FLAGS",
437 "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16|CpuAMX_FP16" },
438 { "CPU_ANY_AVX_VNNI_FLAGS",
440 { "CPU_ANY_MOVDIRI_FLAGS",
442 { "CPU_ANY_UINTR_FLAGS",
444 { "CPU_ANY_MOVDIR64B_FLAGS",
446 { "CPU_ANY_ENQCMD_FLAGS",
448 { "CPU_ANY_SERIALIZE_FLAGS",
450 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
451 "CpuAVX512_VP2INTERSECT" },
452 { "CPU_ANY_TDX_FLAGS",
454 { "CPU_ANY_TSXLDTRK_FLAGS",
456 { "CPU_ANY_KL_FLAGS",
458 { "CPU_ANY_WIDEKL_FLAGS",
460 { "CPU_ANY_HRESET_FLAGS",
462 { "CPU_ANY_AVX512_FP16_FLAGS",
464 { "CPU_ANY_AVX_IFMA_FLAGS",
466 { "CPU_ANY_AVX_VNNI_INT8_FLAGS",
467 "CpuAVX_VNNI_INT8" },
468 { "CPU_ANY_CMPCCXADD_FLAGS",
470 { "CPU_ANY_WRMSRNS_FLAGS",
472 { "CPU_ANY_MSRLIST_FLAGS",
474 { "CPU_ANY_AVX_NE_CONVERT_FLAGS",
475 "CpuAVX_NE_CONVERT" },
476 { "CPU_ANY_RAO_INT_FLAGS",
480 typedef struct bitfield
487 #define BITFIELD(n) { n, 0, #n }
489 static bitfield cpu_flags
[] =
499 BITFIELD (CpuClflush
),
501 BITFIELD (CpuSYSCALL
),
506 BITFIELD (CpuFISTTP
),
512 BITFIELD (CpuSSE4_1
),
513 BITFIELD (CpuSSE4_2
),
516 BITFIELD (CpuAVX512F
),
517 BITFIELD (CpuAVX512CD
),
518 BITFIELD (CpuAVX512ER
),
519 BITFIELD (CpuAVX512PF
),
520 BITFIELD (CpuAVX512VL
),
521 BITFIELD (CpuAVX512DQ
),
522 BITFIELD (CpuAVX512BW
),
526 BITFIELD (Cpu3dnowA
),
527 BITFIELD (CpuPadLock
),
532 BITFIELD (CpuXsaveopt
),
534 BITFIELD (CpuPCLMUL
),
545 BITFIELD (CpuRdtscp
),
546 BITFIELD (CpuFSGSBase
),
551 BITFIELD (CpuPOPCNT
),
554 BITFIELD (CpuINVPCID
),
555 BITFIELD (CpuVMFUNC
),
556 BITFIELD (CpuRDSEED
),
558 BITFIELD (CpuPRFCHW
),
561 BITFIELD (CpuClflushOpt
),
562 BITFIELD (CpuXSAVES
),
563 BITFIELD (CpuXSAVEC
),
564 BITFIELD (CpuPREFETCHWT1
),
568 BITFIELD (CpuAVX512IFMA
),
569 BITFIELD (CpuAVX512VBMI
),
570 BITFIELD (CpuAVX512_4FMAPS
),
571 BITFIELD (CpuAVX512_4VNNIW
),
572 BITFIELD (CpuAVX512_VPOPCNTDQ
),
573 BITFIELD (CpuAVX512_VBMI2
),
574 BITFIELD (CpuAVX512_VNNI
),
575 BITFIELD (CpuAVX512_BITALG
),
576 BITFIELD (CpuAVX512_BF16
),
577 BITFIELD (CpuAVX512_VP2INTERSECT
),
579 BITFIELD (CpuAVX_VNNI
),
580 BITFIELD (CpuAVX512_FP16
),
581 BITFIELD (CpuPREFETCHI
),
582 BITFIELD (CpuAVX_IFMA
),
583 BITFIELD (CpuAVX_VNNI_INT8
),
584 BITFIELD (CpuCMPCCXADD
),
585 BITFIELD (CpuWRMSRNS
),
586 BITFIELD (CpuMSRLIST
),
587 BITFIELD (CpuAVX_NE_CONVERT
),
588 BITFIELD (CpuRAO_INT
),
589 BITFIELD (CpuMWAITX
),
590 BITFIELD (CpuCLZERO
),
593 BITFIELD (CpuPTWRITE
),
598 BITFIELD (CpuVPCLMULQDQ
),
599 BITFIELD (CpuWBNOINVD
),
600 BITFIELD (CpuPCONFIG
),
601 BITFIELD (CpuWAITPKG
),
603 BITFIELD (CpuCLDEMOTE
),
604 BITFIELD (CpuAMX_INT8
),
605 BITFIELD (CpuAMX_BF16
),
606 BITFIELD (CpuAMX_FP16
),
607 BITFIELD (CpuAMX_TILE
),
608 BITFIELD (CpuMOVDIRI
),
609 BITFIELD (CpuMOVDIR64B
),
610 BITFIELD (CpuENQCMD
),
611 BITFIELD (CpuSERIALIZE
),
613 BITFIELD (CpuMCOMMIT
),
614 BITFIELD (CpuSEV_ES
),
615 BITFIELD (CpuTSXLDTRK
),
617 BITFIELD (CpuWideKL
),
618 BITFIELD (CpuHRESET
),
619 BITFIELD (CpuINVLPGB
),
620 BITFIELD (CpuTLBSYNC
),
622 BITFIELD (CpuRMPQUERY
),
626 BITFIELD (CpuUnused
),
630 static bitfield opcode_modifiers
[] =
639 BITFIELD (CheckRegSize
),
640 BITFIELD (OperandConstraint
),
641 BITFIELD (MnemonicSize
),
650 BITFIELD (BNDPrefixOk
),
658 BITFIELD (OpcodeSpace
),
659 BITFIELD (OpcodePrefix
),
660 BITFIELD (VexSources
),
665 BITFIELD (Broadcast
),
666 BITFIELD (StaticRounding
),
668 BITFIELD (Disp8MemShift
),
670 BITFIELD (ATTMnemonic
),
671 BITFIELD (ATTSyntax
),
672 BITFIELD (IntelSyntax
),
676 #define CLASS(n) #n, n
678 static const struct {
680 enum operand_class value
;
681 } operand_classes
[] = {
695 #define INSTANCE(n) #n, n
697 static const struct {
699 enum operand_instance value
;
700 } operand_instances
[] = {
709 static bitfield operand_types
[] =
718 BITFIELD (BaseIndex
),
733 BITFIELD (Unspecified
),
739 static const char *filename
;
740 static i386_cpu_flags active_cpu_flags
;
741 static int active_isstring
;
743 struct template_arg
{
744 const struct template_arg
*next
;
748 struct template_instance
{
749 const struct template_instance
*next
;
751 const struct template_arg
*args
;
754 struct template_param
{
755 const struct template_param
*next
;
760 struct template *next
;
762 const struct template_instance
*instances
;
763 const struct template_param
*params
;
766 static struct template *templates
;
769 compare (const void *x
, const void *y
)
771 const bitfield
*xp
= (const bitfield
*) x
;
772 const bitfield
*yp
= (const bitfield
*) y
;
773 return xp
->position
- yp
->position
;
777 fail (const char *message
, ...)
781 va_start (args
, message
);
782 fprintf (stderr
, _("%s: error: "), program_name
);
783 vfprintf (stderr
, message
, args
);
789 process_copyright (FILE *fp
)
791 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
792 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
794 This file is part of the GNU opcodes library.\n\
796 This library is free software; you can redistribute it and/or modify\n\
797 it under the terms of the GNU General Public License as published by\n\
798 the Free Software Foundation; either version 3, or (at your option)\n\
799 any later version.\n\
801 It is distributed in the hope that it will be useful, but WITHOUT\n\
802 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
803 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
804 License for more details.\n\
806 You should have received a copy of the GNU General Public License\n\
807 along with this program; if not, write to the Free Software\n\
808 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
809 MA 02110-1301, USA. */\n");
812 /* Remove leading white spaces. */
815 remove_leading_whitespaces (char *str
)
817 while (ISSPACE (*str
))
822 /* Remove trailing white spaces. */
825 remove_trailing_whitespaces (char *str
)
827 size_t last
= strlen (str
);
835 if (ISSPACE (str
[last
]))
843 /* Find next field separated by SEP and terminate it. Return a
844 pointer to the one after it. */
847 next_field (char *str
, char sep
, char **next
, char *last
)
851 p
= remove_leading_whitespaces (str
);
852 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
855 remove_trailing_whitespaces (p
);
865 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
868 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
871 char *str
, *next
, *last
;
874 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
875 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
877 /* Turn on selective bits. */
878 char *init
= xstrdup (cpu_flag_init
[i
].init
);
879 last
= init
+ strlen (init
);
880 for (next
= init
; next
&& next
< last
; )
882 str
= next_field (next
, '|', &next
, last
);
884 set_bitfield (str
, array
, 1, size
, lineno
);
894 set_bitfield (char *f
, bitfield
*array
, int value
,
895 unsigned int size
, int lineno
)
899 /* Ignore empty fields; they may result from template expansions. */
903 for (i
= 0; i
< size
; i
++)
904 if (strcasecmp (array
[i
].name
, f
) == 0)
906 array
[i
].value
= value
;
912 const char *v
= strchr (f
, '=');
919 for (i
= 0; i
< size
; i
++)
920 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
922 value
= strtol (v
+ 1, &end
, 0);
925 array
[i
].value
= value
;
933 /* Handle CPU_XXX_FLAGS. */
934 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
938 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
940 fail (_("unknown bitfield: %s\n"), f
);
944 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
945 int macro
, const char *comma
, const char *indent
)
949 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
951 fprintf (table
, "%s{ { ", indent
);
953 for (i
= 0; i
< size
- 1; i
++)
955 if (((i
+ 1) % 20) != 0)
956 fprintf (table
, "%d, ", flags
[i
].value
);
958 fprintf (table
, "%d,", flags
[i
].value
);
959 if (((i
+ 1) % 20) == 0)
961 /* We need \\ for macro. */
963 fprintf (table
, " \\\n %s", indent
);
965 fprintf (table
, "\n %s", indent
);
968 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
971 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
975 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
976 const char *comma
, const char *indent
,
979 char *str
, *next
= flag
, *last
;
982 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
984 /* Copy the default cpu flags. */
985 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
989 last
= flag
+ strlen (flag
);
996 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
1003 /* First we turn on everything except for cpu64, cpuno64, and - if
1004 present - the padding field. */
1005 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1006 if (flags
[i
].position
< Cpu64
)
1009 /* Turn off selective bits. */
1013 if (strcmp (flag
, "0"))
1015 /* Turn on/off selective bits. */
1016 last
= flag
+ strlen (flag
);
1017 for (; next
&& next
< last
; )
1019 str
= next_field (next
, '|', &next
, last
);
1021 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
1025 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1030 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1034 fprintf (table
, " { ");
1036 for (i
= 0; i
< size
- 1; i
++)
1038 if (((i
+ 1) % 20) != 0)
1039 fprintf (table
, "%d, ", modifier
[i
].value
);
1041 fprintf (table
, "%d,", modifier
[i
].value
);
1042 if (((i
+ 1) % 20) == 0)
1043 fprintf (table
, "\n ");
1046 fprintf (table
, "%d },\n", modifier
[i
].value
);
1049 /* Returns LOG2 of element size. */
1051 get_element_size (char **opnd
, int lineno
)
1053 char *str
, *next
, *last
, *op
;
1054 const char *full
= opnd
[0];
1055 int elem_size
= INT_MAX
;
1057 /* Find the memory operand. */
1058 while (full
!= NULL
&& strstr(full
, "BaseIndex") == NULL
)
1061 fail (_("%s: %d: no memory operand\n"), filename
, lineno
);
1063 op
= xstrdup (full
);
1064 last
= op
+ strlen (op
);
1065 for (next
= op
; next
&& next
< last
; )
1067 str
= next_field (next
, '|', &next
, last
);
1070 if (strcasecmp(str
, "Byte") == 0)
1072 /* The smallest element size, no need to check
1077 else if (strcasecmp(str
, "Word") == 0)
1082 else if (strcasecmp(str
, "Dword") == 0)
1087 else if (strcasecmp(str
, "Qword") == 0)
1096 if (elem_size
== INT_MAX
)
1097 fail (_("%s: %d: unknown element size: %s\n"), filename
, lineno
, full
);
1103 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
1104 unsigned int prefix
, char **opnd
, int lineno
)
1106 char *str
, *next
, *last
;
1107 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1109 active_isstring
= 0;
1111 /* Copy the default opcode modifier. */
1112 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1114 if (strcmp (mod
, "0"))
1116 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1118 last
= mod
+ strlen (mod
);
1119 for (next
= mod
; next
&& next
< last
; )
1121 str
= next_field (next
, '|', &next
, last
);
1125 if (strcasecmp(str
, "Broadcast") == 0)
1126 val
= get_element_size (opnd
, lineno
) + BYTE_BROADCAST
;
1127 else if (strcasecmp(str
, "Disp8MemShift") == 0)
1128 val
= get_element_size (opnd
, lineno
);
1130 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1132 if (strcasecmp(str
, "IsString") == 0)
1133 active_isstring
= 1;
1135 if (strcasecmp(str
, "W") == 0)
1138 if (strcasecmp(str
, "No_bSuf") == 0)
1140 if (strcasecmp(str
, "No_wSuf") == 0)
1142 if (strcasecmp(str
, "No_lSuf") == 0)
1144 if (strcasecmp(str
, "No_qSuf") == 0)
1151 if (!modifiers
[OpcodeSpace
].value
)
1152 modifiers
[OpcodeSpace
].value
= space
;
1153 else if (modifiers
[OpcodeSpace
].value
!= space
)
1154 fail (_("%s:%d: Conflicting opcode space specifications\n"),
1158 _("%s:%d: Warning: redundant opcode space specification\n"),
1164 if (!modifiers
[OpcodePrefix
].value
)
1165 modifiers
[OpcodePrefix
].value
= prefix
;
1166 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1167 fail (_("%s:%d: Conflicting prefix specifications\n"),
1171 _("%s:%d: Warning: redundant prefix specification\n"),
1175 if (have_w
&& !bwlq_suf
)
1176 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1177 if (have_w
&& !(bwlq_suf
& 1))
1178 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1180 if (have_w
&& !(bwlq_suf
& ~1))
1182 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1185 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1195 output_operand_type (FILE *table
, enum operand_class
class,
1196 enum operand_instance instance
,
1197 const bitfield
*types
, unsigned int size
,
1198 enum stage stage
, const char *indent
)
1202 fprintf (table
, "{ { %d, %d, ", class, instance
);
1204 for (i
= 0; i
< size
- 1; i
++)
1206 if (((i
+ 3) % 20) != 0)
1207 fprintf (table
, "%d, ", types
[i
].value
);
1209 fprintf (table
, "%d,", types
[i
].value
);
1210 if (((i
+ 3) % 20) == 0)
1212 /* We need \\ for macro. */
1213 if (stage
== stage_macros
)
1214 fprintf (table
, " \\\n%s", indent
);
1216 fprintf (table
, "\n%s", indent
);
1220 fprintf (table
, "%d } }", types
[i
].value
);
1224 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1225 const char *indent
, int lineno
)
1227 char *str
, *next
, *last
;
1228 enum operand_class
class = ClassNone
;
1229 enum operand_instance instance
= InstanceNone
;
1230 bitfield types
[ARRAY_SIZE (operand_types
)];
1232 /* Copy the default operand type. */
1233 memcpy (types
, operand_types
, sizeof (types
));
1235 if (strcmp (op
, "0"))
1239 last
= op
+ strlen (op
);
1240 for (next
= op
; next
&& next
< last
; )
1242 str
= next_field (next
, '|', &next
, last
);
1247 if (!strncmp(str
, "Class=", 6))
1249 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1250 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1252 class = operand_classes
[i
].value
;
1258 if (str
&& !strncmp(str
, "Instance=", 9))
1260 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1261 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1263 instance
= operand_instances
[i
].value
;
1271 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1272 if (strcasecmp(str
, "BaseIndex") == 0)
1277 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1279 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1280 if (!active_cpu_flags
.bitfield
.cpu64
1281 && !active_cpu_flags
.bitfield
.cpumpx
)
1282 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1283 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1286 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1291 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1292 char *last
, int lineno
)
1294 unsigned int i
, length
, prefix
= 0, space
= 0;
1295 char *base_opcode
, *extension_opcode
, *end
;
1296 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1297 unsigned long long opcode
;
1299 /* Find base_opcode. */
1300 base_opcode
= next_field (str
, ',', &str
, last
);
1302 /* Find extension_opcode, if any. */
1303 extension_opcode
= strchr (base_opcode
, '/');
1304 if (extension_opcode
)
1305 *extension_opcode
++ = '\0';
1307 /* Find cpu_flags. */
1308 cpu_flags
= next_field (str
, ',', &str
, last
);
1310 /* Find opcode_modifier. */
1311 opcode_modifier
= next_field (str
, ',', &str
, last
);
1313 /* Remove the first {. */
1314 str
= remove_leading_whitespaces (str
);
1317 str
= remove_leading_whitespaces (str
+ 1);
1318 remove_trailing_whitespaces (str
);
1320 /* Remove } and trailing white space. */
1322 if (!i
|| str
[i
- 1] != '}')
1325 remove_trailing_whitespaces (str
);
1328 operand_types
[i
= 0] = NULL
;
1331 last
= str
+ strlen (str
);
1333 /* Find operand_types. */
1334 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1338 operand_types
[i
] = NULL
;
1342 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1346 opcode
= strtoull (base_opcode
, &end
, 0);
1348 /* Determine opcode length. */
1349 for (length
= 1; length
< 8; ++length
)
1350 if (!(opcode
>> (8 * length
)))
1353 /* Transform prefixes encoded in the opcode into opcode modifier
1357 switch (opcode
>> (8 * length
- 8))
1359 case 0x66: prefix
= PREFIX_0X66
; break;
1360 case 0xF3: prefix
= PREFIX_0XF3
; break;
1361 case 0xF2: prefix
= PREFIX_0XF2
; break;
1365 opcode
&= (1ULL << (8 * --length
)) - 1;
1368 /* Transform opcode space encoded in the opcode into opcode modifier
1370 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1372 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1374 default: space
= SPACE_0F
; break;
1375 case 0x38: space
= SPACE_0F38
; break;
1376 case 0x3A: space
= SPACE_0F3A
; break;
1379 if (space
!= SPACE_0F
&& --length
== 1)
1380 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1381 filename
, lineno
, name
);
1382 opcode
&= (1ULL << (8 * --length
)) - 1;
1386 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1387 filename
, lineno
, name
, 2 * length
, opcode
);
1389 fprintf (table
, " { \"%s\", 0x%0*llx%s, %lu, %s,\n",
1390 name
, 2 * (int)length
, opcode
, end
, i
,
1391 extension_opcode
? extension_opcode
: "None");
1393 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1394 operand_types
, lineno
);
1396 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1398 fprintf (table
, " { ");
1400 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1402 if (!operand_types
[i
])
1405 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1411 fprintf (table
, ",\n ");
1413 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1416 fprintf (table
, " } },\n");
1419 struct opcode_hash_entry
1421 struct opcode_hash_entry
*next
;
1427 /* Calculate the hash value of an opcode hash entry P. */
1430 opcode_hash_hash (const void *p
)
1432 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1433 return htab_hash_string (entry
->name
);
1436 /* Compare a string Q against an opcode hash entry P. */
1439 opcode_hash_eq (const void *p
, const void *q
)
1441 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1442 const char *name
= (const char *) q
;
1443 return strcmp (name
, entry
->name
) == 0;
1447 parse_template (char *buf
, int lineno
)
1449 char sep
, *end
, *name
;
1450 struct template *tmpl
;
1451 struct template_instance
*last_inst
= NULL
;
1453 buf
= remove_leading_whitespaces (buf
+ 1);
1454 end
= strchr (buf
, ':');
1457 struct template *prev
= NULL
;
1459 end
= strchr (buf
, '>');
1461 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1462 if (*remove_leading_whitespaces (end
+ 1))
1463 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1465 remove_trailing_whitespaces (buf
);
1466 /* Don't bother freeing the various structures. */
1467 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1468 if (!strcmp (buf
, tmpl
->name
))
1471 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1473 prev
->next
= tmpl
->next
;
1475 templates
= tmpl
->next
;
1479 remove_trailing_whitespaces (buf
);
1482 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1483 tmpl
= xmalloc (sizeof (*tmpl
));
1484 tmpl
->name
= xstrdup (buf
);
1486 tmpl
->params
= NULL
;
1488 struct template_param
*param
;
1490 buf
= remove_leading_whitespaces (end
);
1491 end
= strpbrk (buf
, ":,");
1493 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1497 remove_trailing_whitespaces (buf
);
1499 param
= xmalloc (sizeof (*param
));
1500 param
->name
= xstrdup (buf
);
1501 param
->next
= tmpl
->params
;
1502 tmpl
->params
= param
;
1503 } while (sep
== ':');
1505 tmpl
->instances
= NULL
;
1507 struct template_instance
*inst
;
1509 const struct template_param
*param
;
1511 buf
= remove_leading_whitespaces (end
);
1512 end
= strpbrk (buf
, ",>");
1514 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1519 inst
= xmalloc (sizeof (*inst
));
1523 cur
= next_field (buf
, ':', &next
, end
);
1524 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1526 for (param
= tmpl
->params
; param
; param
= param
->next
)
1528 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1530 cur
= next_field (next
, ':', &next
, end
);
1532 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1533 arg
->val
= xstrdup (cur
);
1534 arg
->next
= inst
->args
;
1538 if (tmpl
->instances
)
1539 last_inst
->next
= inst
;
1541 tmpl
->instances
= inst
;
1543 } while (sep
== ',');
1545 buf
= remove_leading_whitespaces (end
);
1547 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1548 filename
, lineno
, buf
);
1550 tmpl
->next
= templates
;
1555 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1556 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1558 static unsigned int idx
, opcode_array_size
;
1559 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1560 struct opcode_hash_entry
**hash_slot
, **entry
;
1561 char *ptr1
= strchr(name
, '<'), *ptr2
;
1565 /* Get the slot in hash table. */
1566 hash_slot
= (struct opcode_hash_entry
**)
1567 htab_find_slot_with_hash (opcode_hash_table
, name
,
1568 htab_hash_string (name
),
1571 if (*hash_slot
== NULL
)
1573 /* It is the new one. Put it on opcode array. */
1574 if (idx
>= opcode_array_size
)
1576 /* Grow the opcode array when needed. */
1577 opcode_array_size
+= 1024;
1578 opcode_array
= (struct opcode_hash_entry
**)
1579 xrealloc (opcode_array
,
1580 sizeof (*opcode_array
) * opcode_array_size
);
1581 *opcode_array_p
= opcode_array
;
1584 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1585 xmalloc (sizeof (struct opcode_hash_entry
));
1586 opcode_array
[idx
]->next
= NULL
;
1587 opcode_array
[idx
]->name
= xstrdup (name
);
1588 opcode_array
[idx
]->opcode
= xstrdup (str
);
1589 opcode_array
[idx
]->lineno
= lineno
;
1590 *hash_slot
= opcode_array
[idx
];
1595 /* Append it to the existing one. */
1597 while ((*entry
) != NULL
)
1598 entry
= &(*entry
)->next
;
1599 *entry
= (struct opcode_hash_entry
*)
1600 xmalloc (sizeof (struct opcode_hash_entry
));
1601 (*entry
)->next
= NULL
;
1602 (*entry
)->name
= (*hash_slot
)->name
;
1603 (*entry
)->opcode
= xstrdup (str
);
1604 (*entry
)->lineno
= lineno
;
1607 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1608 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1611 const struct template *tmpl
;
1612 const struct template_instance
*inst
;
1615 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1616 remove_trailing_whitespaces (ptr1
);
1620 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1621 if (!strcmp(ptr1
, tmpl
->name
))
1624 fail ("reference to unknown template '%s'\n", ptr1
);
1626 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1628 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1629 char *str2
= xmalloc(2 * strlen(str
));
1632 strcpy (name2
, name
);
1633 strcat (name2
, inst
->name
);
1634 strcat (name2
, ptr2
);
1636 for (ptr1
= str2
, src
= str
; *src
; )
1638 const char *ident
= tmpl
->name
, *end
;
1639 const struct template_param
*param
;
1640 const struct template_arg
*arg
;
1642 if ((*ptr1
= *src
++) != '<')
1647 while (ISSPACE(*src
))
1649 while (*ident
&& *src
== *ident
)
1651 while (ISSPACE(*src
))
1653 if (*src
!= ':' || *ident
!= '\0')
1655 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1656 ptr1
+= ident
- tmpl
->name
;
1659 while (ISSPACE(*++src
))
1663 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1666 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1667 param
= param
->next
, arg
= arg
->next
)
1669 if (end
- src
== strlen (param
->name
)
1670 && !memcmp (src
, param
->name
, end
- src
))
1678 fail ("template '%s' has no parameter '%.*s'\n",
1679 tmpl
->name
, (int)(end
- src
), src
);
1681 while (ISSPACE(*src
))
1684 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1686 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1687 ptr1
+= strlen(arg
->val
);
1693 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1705 process_i386_opcodes (FILE *table
)
1709 unsigned int i
, j
, nr
;
1710 char *str
, *p
, *last
, *name
;
1711 htab_t opcode_hash_table
;
1712 struct opcode_hash_entry
**opcode_array
= NULL
;
1713 int lineno
= 0, marker
= 0;
1715 filename
= "i386-opc.tbl";
1719 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1720 opcode_hash_eq
, NULL
,
1723 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1724 fprintf (table
, "static const insn_template i386_optab[] =\n{\n");
1726 /* Put everything on opcode array. */
1729 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1732 p
= remove_leading_whitespaces (buf
);
1738 /* Skip comments. */
1739 str
= strstr (p
, "//");
1743 remove_trailing_whitespaces (p
);
1747 /* Look for line continuation character. */
1748 remove_trailing_whitespaces (p
);
1750 if (!j
|| buf
[j
- 1] != '+')
1752 if (j
>= sizeof (buf
) - 1)
1753 fail (_("%s: %d: (continued) line too long\n"), filename
, lineno
);
1755 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1757 fprintf (stderr
, "%s: Line continuation on last line?\n",
1766 if (!strcmp("### MARKER ###", buf
))
1770 /* Since we ignore all included files (we only care about their
1771 #define-s here), we don't need to monitor filenames. The final
1772 line number directive is going to refer to the main source file
1777 p
= remove_leading_whitespaces (p
+ 1);
1778 if (!strncmp(p
, "line", 4))
1780 ln
= strtoul (p
, &end
, 10);
1781 if (ln
> 1 && ln
< INT_MAX
1782 && *remove_leading_whitespaces (end
) == '"')
1785 /* Ignore comments. */
1790 parse_template (p
, lineno
);
1798 last
= p
+ strlen (p
);
1801 name
= next_field (p
, ',', &str
, last
);
1803 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1807 /* Process opcode array. */
1808 for (j
= 0; j
< i
; j
++)
1810 struct opcode_hash_entry
*next
;
1812 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1816 lineno
= next
->lineno
;
1817 last
= str
+ strlen (str
);
1818 output_i386_opcode (table
, name
, str
, last
, lineno
);
1824 fprintf (table
, "};\n");
1826 /* Generate opcode sets array. */
1827 fprintf (table
, "\n/* i386 opcode sets table. */\n\n");
1828 fprintf (table
, "static const insn_template *const i386_op_sets[] =\n{\n");
1829 fprintf (table
, " i386_optab,\n");
1831 for (nr
= j
= 0; j
< i
; j
++)
1833 struct opcode_hash_entry
*next
= opcode_array
[j
];
1841 fprintf (table
, " i386_optab + %u,\n", nr
);
1844 fprintf (table
, "};\n");
1848 process_i386_registers (FILE *table
)
1852 char *str
, *p
, *last
;
1853 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1854 char *dw2_32_num
, *dw2_64_num
;
1857 filename
= "i386-reg.tbl";
1858 fp
= fopen (filename
, "r");
1860 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1863 fprintf (table
, "\n/* i386 register table. */\n\n");
1864 fprintf (table
, "static const reg_entry i386_regtab[] =\n{\n");
1868 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1873 p
= remove_leading_whitespaces (buf
);
1875 /* Skip comments. */
1876 str
= strstr (p
, "//");
1880 /* Remove trailing white spaces. */
1881 remove_trailing_whitespaces (p
);
1886 fprintf (table
, "%s\n", p
);
1894 last
= p
+ strlen (p
);
1896 /* Find reg_name. */
1897 reg_name
= next_field (p
, ',', &str
, last
);
1899 /* Find reg_type. */
1900 reg_type
= next_field (str
, ',', &str
, last
);
1902 /* Find reg_flags. */
1903 reg_flags
= next_field (str
, ',', &str
, last
);
1906 reg_num
= next_field (str
, ',', &str
, last
);
1908 fprintf (table
, " { \"%s\",\n ", reg_name
);
1910 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1913 /* Find 32-bit Dwarf2 register number. */
1914 dw2_32_num
= next_field (str
, ',', &str
, last
);
1916 /* Find 64-bit Dwarf2 register number. */
1917 dw2_64_num
= next_field (str
, ',', &str
, last
);
1919 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1920 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1925 fprintf (table
, "};\n");
1927 fprintf (table
, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1931 process_i386_initializers (void)
1934 FILE *fp
= fopen ("i386-init.h", "w");
1938 fail (_("can't create i386-init.h, errno = %s\n"),
1941 process_copyright (fp
);
1943 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1945 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1946 init
= xstrdup (cpu_flag_init
[i
].init
);
1947 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1956 /* Program options. */
1957 #define OPTION_SRCDIR 200
1959 struct option long_options
[] =
1961 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1962 {"debug", no_argument
, NULL
, 'd'},
1963 {"version", no_argument
, NULL
, 'V'},
1964 {"help", no_argument
, NULL
, 'h'},
1965 {0, no_argument
, NULL
, 0}
1969 print_version (void)
1971 printf ("%s: version 1.0\n", program_name
);
1976 usage (FILE * stream
, int status
)
1978 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1984 main (int argc
, char **argv
)
1986 extern int chdir (char *);
1987 char *srcdir
= NULL
;
1989 unsigned int i
, cpumax
;
1992 program_name
= *argv
;
1993 xmalloc_set_program_name (program_name
);
1995 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2020 if (chdir (srcdir
) != 0)
2021 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2022 srcdir
, xstrerror (errno
));
2024 /* cpu_flags isn't sorted by position. */
2026 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2027 if (cpu_flags
[i
].position
> cpumax
)
2028 cpumax
= cpu_flags
[i
].position
;
2030 /* Check the unused bitfield in i386_cpu_flags. */
2032 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2034 if ((cpumax
- 1) != CpuMax
)
2035 fail (_("CpuMax != %d!\n"), cpumax
);
2037 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2039 if (cpumax
!= CpuMax
)
2040 fail (_("CpuMax != %d!\n"), cpumax
);
2042 c
= CpuNumOfBits
- CpuMax
- 1;
2044 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2047 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2049 /* Check the unused bitfield in i386_operand_type. */
2051 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2054 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2057 c
= OTNumOfBits
- OTNum
;
2059 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2062 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2065 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2066 sizeof (opcode_modifiers
[0]), compare
);
2068 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2069 sizeof (operand_types
[0]), compare
);
2071 table
= fopen ("i386-tbl.h", "w");
2073 fail (_("can't create i386-tbl.h, errno = %s\n"),
2076 process_copyright (table
);
2078 process_i386_opcodes (table
);
2079 process_i386_registers (table
);
2080 process_i386_initializers ();