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. */
1303 extension_opcode
= next_field (str
, ',', &str
, last
);
1305 /* Find cpu_flags. */
1306 cpu_flags
= next_field (str
, ',', &str
, last
);
1308 /* Find opcode_modifier. */
1309 opcode_modifier
= next_field (str
, ',', &str
, last
);
1311 /* Remove the first {. */
1312 str
= remove_leading_whitespaces (str
);
1315 str
= remove_leading_whitespaces (str
+ 1);
1316 remove_trailing_whitespaces (str
);
1318 /* Remove } and trailing white space. */
1320 if (!i
|| str
[i
- 1] != '}')
1323 remove_trailing_whitespaces (str
);
1326 operand_types
[i
= 0] = NULL
;
1329 last
= str
+ strlen (str
);
1331 /* Find operand_types. */
1332 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1336 operand_types
[i
] = NULL
;
1340 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1344 opcode
= strtoull (base_opcode
, &end
, 0);
1346 /* Determine opcode length. */
1347 for (length
= 1; length
< 8; ++length
)
1348 if (!(opcode
>> (8 * length
)))
1351 /* Transform prefixes encoded in the opcode into opcode modifier
1355 switch (opcode
>> (8 * length
- 8))
1357 case 0x66: prefix
= PREFIX_0X66
; break;
1358 case 0xF3: prefix
= PREFIX_0XF3
; break;
1359 case 0xF2: prefix
= PREFIX_0XF2
; break;
1363 opcode
&= (1ULL << (8 * --length
)) - 1;
1366 /* Transform opcode space encoded in the opcode into opcode modifier
1368 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1370 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1372 default: space
= SPACE_0F
; break;
1373 case 0x38: space
= SPACE_0F38
; break;
1374 case 0x3A: space
= SPACE_0F3A
; break;
1377 if (space
!= SPACE_0F
&& --length
== 1)
1378 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1379 filename
, lineno
, name
);
1380 opcode
&= (1ULL << (8 * --length
)) - 1;
1384 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1385 filename
, lineno
, name
, 2 * length
, opcode
);
1387 fprintf (table
, " { \"%s\", 0x%0*llx%s, %lu, %s,\n",
1388 name
, 2 * (int)length
, opcode
, end
, i
, extension_opcode
);
1390 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1391 operand_types
, lineno
);
1393 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1395 fprintf (table
, " { ");
1397 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1399 if (!operand_types
[i
])
1402 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1408 fprintf (table
, ",\n ");
1410 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1413 fprintf (table
, " } },\n");
1416 struct opcode_hash_entry
1418 struct opcode_hash_entry
*next
;
1424 /* Calculate the hash value of an opcode hash entry P. */
1427 opcode_hash_hash (const void *p
)
1429 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1430 return htab_hash_string (entry
->name
);
1433 /* Compare a string Q against an opcode hash entry P. */
1436 opcode_hash_eq (const void *p
, const void *q
)
1438 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1439 const char *name
= (const char *) q
;
1440 return strcmp (name
, entry
->name
) == 0;
1444 parse_template (char *buf
, int lineno
)
1446 char sep
, *end
, *name
;
1447 struct template *tmpl
;
1448 struct template_instance
*last_inst
= NULL
;
1450 buf
= remove_leading_whitespaces (buf
+ 1);
1451 end
= strchr (buf
, ':');
1454 struct template *prev
= NULL
;
1456 end
= strchr (buf
, '>');
1458 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1459 if (*remove_leading_whitespaces (end
+ 1))
1460 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1462 remove_trailing_whitespaces (buf
);
1463 /* Don't bother freeing the various structures. */
1464 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1465 if (!strcmp (buf
, tmpl
->name
))
1468 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1470 prev
->next
= tmpl
->next
;
1472 templates
= tmpl
->next
;
1476 remove_trailing_whitespaces (buf
);
1479 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1480 tmpl
= xmalloc (sizeof (*tmpl
));
1481 tmpl
->name
= xstrdup (buf
);
1483 tmpl
->params
= NULL
;
1485 struct template_param
*param
;
1487 buf
= remove_leading_whitespaces (end
);
1488 end
= strpbrk (buf
, ":,");
1490 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1494 remove_trailing_whitespaces (buf
);
1496 param
= xmalloc (sizeof (*param
));
1497 param
->name
= xstrdup (buf
);
1498 param
->next
= tmpl
->params
;
1499 tmpl
->params
= param
;
1500 } while (sep
== ':');
1502 tmpl
->instances
= NULL
;
1504 struct template_instance
*inst
;
1506 const struct template_param
*param
;
1508 buf
= remove_leading_whitespaces (end
);
1509 end
= strpbrk (buf
, ",>");
1511 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1516 inst
= xmalloc (sizeof (*inst
));
1520 cur
= next_field (buf
, ':', &next
, end
);
1521 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1523 for (param
= tmpl
->params
; param
; param
= param
->next
)
1525 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1527 cur
= next_field (next
, ':', &next
, end
);
1529 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1530 arg
->val
= xstrdup (cur
);
1531 arg
->next
= inst
->args
;
1535 if (tmpl
->instances
)
1536 last_inst
->next
= inst
;
1538 tmpl
->instances
= inst
;
1540 } while (sep
== ',');
1542 buf
= remove_leading_whitespaces (end
);
1544 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1545 filename
, lineno
, buf
);
1547 tmpl
->next
= templates
;
1552 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1553 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1555 static unsigned int idx
, opcode_array_size
;
1556 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1557 struct opcode_hash_entry
**hash_slot
, **entry
;
1558 char *ptr1
= strchr(name
, '<'), *ptr2
;
1562 /* Get the slot in hash table. */
1563 hash_slot
= (struct opcode_hash_entry
**)
1564 htab_find_slot_with_hash (opcode_hash_table
, name
,
1565 htab_hash_string (name
),
1568 if (*hash_slot
== NULL
)
1570 /* It is the new one. Put it on opcode array. */
1571 if (idx
>= opcode_array_size
)
1573 /* Grow the opcode array when needed. */
1574 opcode_array_size
+= 1024;
1575 opcode_array
= (struct opcode_hash_entry
**)
1576 xrealloc (opcode_array
,
1577 sizeof (*opcode_array
) * opcode_array_size
);
1578 *opcode_array_p
= opcode_array
;
1581 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1582 xmalloc (sizeof (struct opcode_hash_entry
));
1583 opcode_array
[idx
]->next
= NULL
;
1584 opcode_array
[idx
]->name
= xstrdup (name
);
1585 opcode_array
[idx
]->opcode
= xstrdup (str
);
1586 opcode_array
[idx
]->lineno
= lineno
;
1587 *hash_slot
= opcode_array
[idx
];
1592 /* Append it to the existing one. */
1594 while ((*entry
) != NULL
)
1595 entry
= &(*entry
)->next
;
1596 *entry
= (struct opcode_hash_entry
*)
1597 xmalloc (sizeof (struct opcode_hash_entry
));
1598 (*entry
)->next
= NULL
;
1599 (*entry
)->name
= (*hash_slot
)->name
;
1600 (*entry
)->opcode
= xstrdup (str
);
1601 (*entry
)->lineno
= lineno
;
1604 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1605 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1608 const struct template *tmpl
;
1609 const struct template_instance
*inst
;
1612 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1613 remove_trailing_whitespaces (ptr1
);
1617 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1618 if (!strcmp(ptr1
, tmpl
->name
))
1621 fail ("reference to unknown template '%s'\n", ptr1
);
1623 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1625 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1626 char *str2
= xmalloc(2 * strlen(str
));
1629 strcpy (name2
, name
);
1630 strcat (name2
, inst
->name
);
1631 strcat (name2
, ptr2
);
1633 for (ptr1
= str2
, src
= str
; *src
; )
1635 const char *ident
= tmpl
->name
, *end
;
1636 const struct template_param
*param
;
1637 const struct template_arg
*arg
;
1639 if ((*ptr1
= *src
++) != '<')
1644 while (ISSPACE(*src
))
1646 while (*ident
&& *src
== *ident
)
1648 while (ISSPACE(*src
))
1650 if (*src
!= ':' || *ident
!= '\0')
1652 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1653 ptr1
+= ident
- tmpl
->name
;
1656 while (ISSPACE(*++src
))
1660 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1663 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1664 param
= param
->next
, arg
= arg
->next
)
1666 if (end
- src
== strlen (param
->name
)
1667 && !memcmp (src
, param
->name
, end
- src
))
1675 fail ("template '%s' has no parameter '%.*s'\n",
1676 tmpl
->name
, (int)(end
- src
), src
);
1678 while (ISSPACE(*src
))
1681 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1683 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1684 ptr1
+= strlen(arg
->val
);
1690 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1702 process_i386_opcodes (FILE *table
)
1707 char *str
, *p
, *last
, *name
;
1708 htab_t opcode_hash_table
;
1709 struct opcode_hash_entry
**opcode_array
= NULL
;
1710 int lineno
= 0, marker
= 0;
1712 filename
= "i386-opc.tbl";
1716 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1717 opcode_hash_eq
, NULL
,
1720 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1721 fprintf (table
, "static const insn_template i386_optab[] =\n{\n");
1723 /* Put everything on opcode array. */
1726 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1729 p
= remove_leading_whitespaces (buf
);
1735 /* Skip comments. */
1736 str
= strstr (p
, "//");
1740 remove_trailing_whitespaces (p
);
1744 /* Look for line continuation character. */
1745 remove_trailing_whitespaces (p
);
1747 if (!j
|| buf
[j
- 1] != '+')
1749 if (j
>= sizeof (buf
) - 1)
1750 fail (_("%s: %d: (continued) line too long\n"), filename
, lineno
);
1752 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1754 fprintf (stderr
, "%s: Line continuation on last line?\n",
1763 if (!strcmp("### MARKER ###", buf
))
1767 /* Since we ignore all included files (we only care about their
1768 #define-s here), we don't need to monitor filenames. The final
1769 line number directive is going to refer to the main source file
1774 p
= remove_leading_whitespaces (p
+ 1);
1775 if (!strncmp(p
, "line", 4))
1777 ln
= strtoul (p
, &end
, 10);
1778 if (ln
> 1 && ln
< INT_MAX
1779 && *remove_leading_whitespaces (end
) == '"')
1782 /* Ignore comments. */
1787 parse_template (p
, lineno
);
1795 last
= p
+ strlen (p
);
1798 name
= next_field (p
, ',', &str
, last
);
1800 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1804 /* Process opcode array. */
1805 for (j
= 0; j
< i
; j
++)
1807 struct opcode_hash_entry
*next
;
1809 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1813 lineno
= next
->lineno
;
1814 last
= str
+ strlen (str
);
1815 output_i386_opcode (table
, name
, str
, last
, lineno
);
1821 fprintf (table
, "};\n");
1825 process_i386_registers (FILE *table
)
1829 char *str
, *p
, *last
;
1830 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1831 char *dw2_32_num
, *dw2_64_num
;
1834 filename
= "i386-reg.tbl";
1835 fp
= fopen (filename
, "r");
1837 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1840 fprintf (table
, "\n/* i386 register table. */\n\n");
1841 fprintf (table
, "static const reg_entry i386_regtab[] =\n{\n");
1845 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1850 p
= remove_leading_whitespaces (buf
);
1852 /* Skip comments. */
1853 str
= strstr (p
, "//");
1857 /* Remove trailing white spaces. */
1858 remove_trailing_whitespaces (p
);
1863 fprintf (table
, "%s\n", p
);
1871 last
= p
+ strlen (p
);
1873 /* Find reg_name. */
1874 reg_name
= next_field (p
, ',', &str
, last
);
1876 /* Find reg_type. */
1877 reg_type
= next_field (str
, ',', &str
, last
);
1879 /* Find reg_flags. */
1880 reg_flags
= next_field (str
, ',', &str
, last
);
1883 reg_num
= next_field (str
, ',', &str
, last
);
1885 fprintf (table
, " { \"%s\",\n ", reg_name
);
1887 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1890 /* Find 32-bit Dwarf2 register number. */
1891 dw2_32_num
= next_field (str
, ',', &str
, last
);
1893 /* Find 64-bit Dwarf2 register number. */
1894 dw2_64_num
= next_field (str
, ',', &str
, last
);
1896 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1897 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1902 fprintf (table
, "};\n");
1904 fprintf (table
, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1908 process_i386_initializers (void)
1911 FILE *fp
= fopen ("i386-init.h", "w");
1915 fail (_("can't create i386-init.h, errno = %s\n"),
1918 process_copyright (fp
);
1920 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1922 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1923 init
= xstrdup (cpu_flag_init
[i
].init
);
1924 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1933 /* Program options. */
1934 #define OPTION_SRCDIR 200
1936 struct option long_options
[] =
1938 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1939 {"debug", no_argument
, NULL
, 'd'},
1940 {"version", no_argument
, NULL
, 'V'},
1941 {"help", no_argument
, NULL
, 'h'},
1942 {0, no_argument
, NULL
, 0}
1946 print_version (void)
1948 printf ("%s: version 1.0\n", program_name
);
1953 usage (FILE * stream
, int status
)
1955 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1961 main (int argc
, char **argv
)
1963 extern int chdir (char *);
1964 char *srcdir
= NULL
;
1966 unsigned int i
, cpumax
;
1969 program_name
= *argv
;
1970 xmalloc_set_program_name (program_name
);
1972 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1997 if (chdir (srcdir
) != 0)
1998 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1999 srcdir
, xstrerror (errno
));
2001 /* cpu_flags isn't sorted by position. */
2003 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2004 if (cpu_flags
[i
].position
> cpumax
)
2005 cpumax
= cpu_flags
[i
].position
;
2007 /* Check the unused bitfield in i386_cpu_flags. */
2009 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2011 if ((cpumax
- 1) != CpuMax
)
2012 fail (_("CpuMax != %d!\n"), cpumax
);
2014 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2016 if (cpumax
!= CpuMax
)
2017 fail (_("CpuMax != %d!\n"), cpumax
);
2019 c
= CpuNumOfBits
- CpuMax
- 1;
2021 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2024 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2026 /* Check the unused bitfield in i386_operand_type. */
2028 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2031 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2034 c
= OTNumOfBits
- OTNum
;
2036 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2039 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2042 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2043 sizeof (opcode_modifiers
[0]), compare
);
2045 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2046 sizeof (operand_types
[0]), compare
);
2048 table
= fopen ("i386-tbl.h", "w");
2050 fail (_("can't create i386-tbl.h, errno = %s\n"),
2053 process_copyright (table
);
2055 process_i386_opcodes (table
);
2056 process_i386_registers (table
);
2057 process_i386_initializers ();