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",
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|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_BTVER1_FLAGS",
109 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME" },
110 { "CPU_BTVER2_FLAGS",
111 "CPU_BTVER1_FLAGS|CPU_AVX_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuMovbe|CpuXsaveopt|CpuPRFCHW" },
119 "CPU_387_FLAGS|Cpu687" },
124 { "CPU_CLFLUSH_FLAGS",
128 { "CPU_SYSCALL_FLAGS",
135 "CPU_SSE_FLAGS|CpuSSE2" },
137 "CPU_SSE2_FLAGS|CpuSSE3" },
139 "CPU_SSE3_FLAGS|CpuSSSE3" },
140 { "CPU_SSE4_1_FLAGS",
141 "CPU_SSSE3_FLAGS|CpuSSE4_1" },
142 { "CPU_SSE4_2_FLAGS",
143 "CPU_SSE4_1_FLAGS|CpuSSE4_2|CpuPOPCNT" },
150 { "CPU_XSAVEOPT_FLAGS",
151 "CPU_XSAVE_FLAGS|CpuXsaveopt" },
153 "CPU_SSE2_FLAGS|CpuAES" },
154 { "CPU_PCLMUL_FLAGS",
155 "CPU_SSE2_FLAGS|CpuPCLMUL" },
157 "CPU_AVX_FLAGS|CpuFMA" },
159 "CPU_AVX_FLAGS|CpuFMA4" },
161 "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
163 "CPU_XSAVE_FLAGS|CpuLWP" },
172 { "CPU_RDTSCP_FLAGS",
176 { "CPU_FSGSBASE_FLAGS",
181 "CPU_AVX_FLAGS|CpuF16C" },
186 { "CPU_POPCNT_FLAGS",
192 { "CPU_INVPCID_FLAGS",
194 { "CPU_VMFUNC_FLAGS",
197 "CPU_MMX_FLAGS|Cpu3dnow" },
198 { "CPU_3DNOWA_FLAGS",
199 "CPU_3DNOW_FLAGS|Cpu3dnowA" },
200 { "CPU_PADLOCK_FLAGS",
205 "CPU_SSE3_FLAGS|CpuSSE4a" },
207 "CpuLZCNT|CpuPOPCNT" },
209 "CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
211 "CPU_AVX_FLAGS|CpuAVX2" },
212 { "CPU_AVX_VNNI_FLAGS",
213 "CPU_AVX2_FLAGS|CpuAVX_VNNI" },
214 { "CPU_AVX512F_FLAGS",
215 "CPU_AVX2_FLAGS|CpuAVX512F" },
216 { "CPU_AVX512CD_FLAGS",
217 "CPU_AVX512F_FLAGS|CpuAVX512CD" },
218 { "CPU_AVX512ER_FLAGS",
219 "CPU_AVX512F_FLAGS|CpuAVX512ER" },
220 { "CPU_AVX512PF_FLAGS",
221 "CPU_AVX512F_FLAGS|CpuAVX512PF" },
222 { "CPU_AVX512DQ_FLAGS",
223 "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
224 { "CPU_AVX512BW_FLAGS",
225 "CPU_AVX512F_FLAGS|CpuAVX512BW" },
226 { "CPU_AVX512VL_FLAGS",
227 "CPU_AVX512F_FLAGS|CpuAVX512VL" },
228 { "CPU_AVX512IFMA_FLAGS",
229 "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
230 { "CPU_AVX512VBMI_FLAGS",
231 "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
232 { "CPU_AVX512_4FMAPS_FLAGS",
233 "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
234 { "CPU_AVX512_4VNNIW_FLAGS",
235 "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
236 { "CPU_AVX512_VPOPCNTDQ_FLAGS",
237 "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
238 { "CPU_AVX512_VBMI2_FLAGS",
239 "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
240 { "CPU_AVX512_VNNI_FLAGS",
241 "CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
242 { "CPU_AVX512_BITALG_FLAGS",
243 "CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
244 { "CPU_AVX512_BF16_FLAGS",
245 "CPU_AVX512F_FLAGS|CpuAVX512_BF16" },
246 { "CPU_AVX512_FP16_FLAGS",
247 "CPU_AVX512BW_FLAGS|CpuAVX512_FP16" },
253 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
256 { "CPU_RDSEED_FLAGS",
258 { "CPU_PRFCHW_FLAGS",
263 "CPU_XSAVE_FLAGS|CpuMPX" },
265 "CPU_SSE2_FLAGS|CpuSHA" },
266 { "CPU_CLFLUSHOPT_FLAGS",
268 { "CPU_XSAVES_FLAGS",
269 "CPU_XSAVE_FLAGS|CpuXSAVES" },
270 { "CPU_XSAVEC_FLAGS",
271 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
272 { "CPU_PREFETCHWT1_FLAGS",
278 { "CPU_CLZERO_FLAGS",
280 { "CPU_MWAITX_FLAGS",
283 "CPU_XSAVE_FLAGS|CpuOSPKE" },
286 { "CPU_PTWRITE_FLAGS",
296 { "CPU_VPCLMULQDQ_FLAGS",
298 { "CPU_WBNOINVD_FLAGS",
300 { "CPU_PCONFIG_FLAGS",
302 { "CPU_WAITPKG_FLAGS",
306 { "CPU_CLDEMOTE_FLAGS",
308 { "CPU_AMX_INT8_FLAGS",
310 { "CPU_AMX_BF16_FLAGS",
312 { "CPU_AMX_TILE_FLAGS",
314 { "CPU_MOVDIRI_FLAGS",
316 { "CPU_MOVDIR64B_FLAGS",
318 { "CPU_ENQCMD_FLAGS",
320 { "CPU_SERIALIZE_FLAGS",
322 { "CPU_AVX512_VP2INTERSECT_FLAGS",
323 "CpuAVX512_VP2INTERSECT" },
328 { "CPU_MCOMMIT_FLAGS",
330 { "CPU_SEV_ES_FLAGS",
332 { "CPU_TSXLDTRK_FLAGS",
336 { "CPU_WIDEKL_FLAGS",
338 { "CPU_HRESET_FLAGS",
340 { "CPU_INVLPGB_FLAGS",
342 { "CPU_TLBSYNC_FLAGS",
346 { "CPU_ANY_X87_FLAGS",
347 "CPU_ANY_287_FLAGS|Cpu8087" },
348 { "CPU_ANY_287_FLAGS",
349 "CPU_ANY_387_FLAGS|Cpu287" },
350 { "CPU_ANY_387_FLAGS",
351 "CPU_ANY_687_FLAGS|Cpu387" },
352 { "CPU_ANY_687_FLAGS",
353 "Cpu687|CpuFISTTP" },
354 { "CPU_ANY_CMOV_FLAGS",
356 { "CPU_ANY_FXSR_FLAGS",
358 { "CPU_ANY_MMX_FLAGS",
359 "CPU_3DNOWA_FLAGS" },
360 { "CPU_ANY_SSE_FLAGS",
361 "CPU_ANY_SSE2_FLAGS|CpuSSE" },
362 { "CPU_ANY_SSE2_FLAGS",
363 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
364 { "CPU_ANY_SSE3_FLAGS",
365 "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
366 { "CPU_ANY_SSSE3_FLAGS",
367 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
368 { "CPU_ANY_SSE4_1_FLAGS",
369 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
370 { "CPU_ANY_SSE4_2_FLAGS",
372 { "CPU_ANY_SSE4A_FLAGS",
374 { "CPU_ANY_AVX_FLAGS",
375 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
376 { "CPU_ANY_AVX2_FLAGS",
377 "CPU_ANY_AVX512F_FLAGS|CpuAVX2" },
378 { "CPU_ANY_AVX512F_FLAGS",
379 "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" },
380 { "CPU_ANY_AVX512CD_FLAGS",
382 { "CPU_ANY_AVX512ER_FLAGS",
384 { "CPU_ANY_AVX512PF_FLAGS",
386 { "CPU_ANY_AVX512DQ_FLAGS",
388 { "CPU_ANY_AVX512BW_FLAGS",
389 "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
390 { "CPU_ANY_AVX512VL_FLAGS",
392 { "CPU_ANY_AVX512IFMA_FLAGS",
394 { "CPU_ANY_AVX512VBMI_FLAGS",
396 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
397 "CpuAVX512_4FMAPS" },
398 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
399 "CpuAVX512_4VNNIW" },
400 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
401 "CpuAVX512_VPOPCNTDQ" },
402 { "CPU_ANY_IBT_FLAGS",
404 { "CPU_ANY_SHSTK_FLAGS",
406 { "CPU_ANY_AVX512_VBMI2_FLAGS",
408 { "CPU_ANY_AVX512_VNNI_FLAGS",
410 { "CPU_ANY_AVX512_BITALG_FLAGS",
411 "CpuAVX512_BITALG" },
412 { "CPU_ANY_AVX512_BF16_FLAGS",
414 { "CPU_ANY_AMX_INT8_FLAGS",
416 { "CPU_ANY_AMX_BF16_FLAGS",
418 { "CPU_ANY_AMX_TILE_FLAGS",
419 "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16" },
420 { "CPU_ANY_AVX_VNNI_FLAGS",
422 { "CPU_ANY_MOVDIRI_FLAGS",
424 { "CPU_ANY_UINTR_FLAGS",
426 { "CPU_ANY_MOVDIR64B_FLAGS",
428 { "CPU_ANY_ENQCMD_FLAGS",
430 { "CPU_ANY_SERIALIZE_FLAGS",
432 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
433 "CpuAVX512_VP2INTERSECT" },
434 { "CPU_ANY_TDX_FLAGS",
436 { "CPU_ANY_TSXLDTRK_FLAGS",
438 { "CPU_ANY_KL_FLAGS",
440 { "CPU_ANY_WIDEKL_FLAGS",
442 { "CPU_ANY_HRESET_FLAGS",
444 { "CPU_ANY_AVX512_FP16_FLAGS",
448 static initializer operand_type_init
[] =
450 { "OPERAND_TYPE_NONE",
452 { "OPERAND_TYPE_REG8",
454 { "OPERAND_TYPE_REG16",
456 { "OPERAND_TYPE_REG32",
458 { "OPERAND_TYPE_REG64",
460 { "OPERAND_TYPE_IMM1",
462 { "OPERAND_TYPE_IMM8",
464 { "OPERAND_TYPE_IMM8S",
466 { "OPERAND_TYPE_IMM16",
468 { "OPERAND_TYPE_IMM32",
470 { "OPERAND_TYPE_IMM32S",
472 { "OPERAND_TYPE_IMM64",
474 { "OPERAND_TYPE_BASEINDEX",
476 { "OPERAND_TYPE_DISP8",
478 { "OPERAND_TYPE_DISP16",
480 { "OPERAND_TYPE_DISP32",
482 { "OPERAND_TYPE_DISP32S",
484 { "OPERAND_TYPE_DISP64",
486 { "OPERAND_TYPE_INOUTPORTREG",
487 "Instance=RegD|Word" },
488 { "OPERAND_TYPE_SHIFTCOUNT",
489 "Instance=RegC|Byte" },
490 { "OPERAND_TYPE_CONTROL",
492 { "OPERAND_TYPE_TEST",
494 { "OPERAND_TYPE_DEBUG",
496 { "OPERAND_TYPE_FLOATREG",
498 { "OPERAND_TYPE_FLOATACC",
499 "Instance=Accum|Tbyte" },
500 { "OPERAND_TYPE_SREG",
502 { "OPERAND_TYPE_REGMMX",
504 { "OPERAND_TYPE_REGXMM",
505 "Class=RegSIMD|Xmmword" },
506 { "OPERAND_TYPE_REGYMM",
507 "Class=RegSIMD|Ymmword" },
508 { "OPERAND_TYPE_REGZMM",
509 "Class=RegSIMD|Zmmword" },
510 { "OPERAND_TYPE_REGTMM",
511 "Class=RegSIMD|Tmmword" },
512 { "OPERAND_TYPE_REGMASK",
514 { "OPERAND_TYPE_REGBND",
516 { "OPERAND_TYPE_ACC8",
517 "Instance=Accum|Byte" },
518 { "OPERAND_TYPE_ACC16",
519 "Instance=Accum|Word" },
520 { "OPERAND_TYPE_ACC32",
521 "Instance=Accum|Dword" },
522 { "OPERAND_TYPE_ACC64",
523 "Instance=Accum|Qword" },
524 { "OPERAND_TYPE_DISP16_32",
526 { "OPERAND_TYPE_ANYDISP",
527 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
528 { "OPERAND_TYPE_IMM16_32",
530 { "OPERAND_TYPE_IMM16_32S",
532 { "OPERAND_TYPE_IMM16_32_32S",
533 "Imm16|Imm32|Imm32S" },
534 { "OPERAND_TYPE_IMM32_64",
536 { "OPERAND_TYPE_IMM32_32S_DISP32",
537 "Imm32|Imm32S|Disp32" },
538 { "OPERAND_TYPE_IMM64_DISP64",
540 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
541 "Imm32|Imm32S|Imm64|Disp32" },
542 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
543 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
544 { "OPERAND_TYPE_ANYIMM",
545 "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
548 typedef struct bitfield
555 #define BITFIELD(n) { n, 0, #n }
557 static bitfield cpu_flags
[] =
567 BITFIELD (CpuClflush
),
569 BITFIELD (CpuSYSCALL
),
574 BITFIELD (CpuFISTTP
),
580 BITFIELD (CpuSSE4_1
),
581 BITFIELD (CpuSSE4_2
),
584 BITFIELD (CpuAVX512F
),
585 BITFIELD (CpuAVX512CD
),
586 BITFIELD (CpuAVX512ER
),
587 BITFIELD (CpuAVX512PF
),
588 BITFIELD (CpuAVX512VL
),
589 BITFIELD (CpuAVX512DQ
),
590 BITFIELD (CpuAVX512BW
),
596 BITFIELD (Cpu3dnowA
),
597 BITFIELD (CpuPadLock
),
602 BITFIELD (CpuXsaveopt
),
604 BITFIELD (CpuPCLMUL
),
615 BITFIELD (CpuRdtscp
),
616 BITFIELD (CpuFSGSBase
),
621 BITFIELD (CpuPOPCNT
),
624 BITFIELD (CpuINVPCID
),
625 BITFIELD (CpuVMFUNC
),
626 BITFIELD (CpuRDSEED
),
628 BITFIELD (CpuPRFCHW
),
631 BITFIELD (CpuClflushOpt
),
632 BITFIELD (CpuXSAVES
),
633 BITFIELD (CpuXSAVEC
),
634 BITFIELD (CpuPREFETCHWT1
),
640 BITFIELD (CpuAVX512IFMA
),
641 BITFIELD (CpuAVX512VBMI
),
642 BITFIELD (CpuAVX512_4FMAPS
),
643 BITFIELD (CpuAVX512_4VNNIW
),
644 BITFIELD (CpuAVX512_VPOPCNTDQ
),
645 BITFIELD (CpuAVX512_VBMI2
),
646 BITFIELD (CpuAVX512_VNNI
),
647 BITFIELD (CpuAVX512_BITALG
),
648 BITFIELD (CpuAVX512_BF16
),
649 BITFIELD (CpuAVX512_VP2INTERSECT
),
651 BITFIELD (CpuAVX_VNNI
),
652 BITFIELD (CpuAVX512_FP16
),
653 BITFIELD (CpuMWAITX
),
654 BITFIELD (CpuCLZERO
),
657 BITFIELD (CpuPTWRITE
),
662 BITFIELD (CpuVPCLMULQDQ
),
663 BITFIELD (CpuWBNOINVD
),
664 BITFIELD (CpuPCONFIG
),
665 BITFIELD (CpuWAITPKG
),
667 BITFIELD (CpuCLDEMOTE
),
668 BITFIELD (CpuAMX_INT8
),
669 BITFIELD (CpuAMX_BF16
),
670 BITFIELD (CpuAMX_TILE
),
671 BITFIELD (CpuMOVDIRI
),
672 BITFIELD (CpuMOVDIR64B
),
673 BITFIELD (CpuENQCMD
),
674 BITFIELD (CpuSERIALIZE
),
676 BITFIELD (CpuMCOMMIT
),
677 BITFIELD (CpuSEV_ES
),
678 BITFIELD (CpuTSXLDTRK
),
680 BITFIELD (CpuWideKL
),
681 BITFIELD (CpuHRESET
),
682 BITFIELD (CpuINVLPGB
),
683 BITFIELD (CpuTLBSYNC
),
686 BITFIELD (CpuUnused
),
690 static bitfield opcode_modifiers
[] =
700 BITFIELD (CheckRegSize
),
701 BITFIELD (DistinctDest
),
702 BITFIELD (MnemonicSize
),
713 BITFIELD (BNDPrefixOk
),
714 BITFIELD (RegKludge
),
715 BITFIELD (Implicit1stXmm0
),
719 BITFIELD (AddrPrefixOpReg
),
724 BITFIELD (PseudoVexPrefix
),
728 BITFIELD (OpcodeSpace
),
729 BITFIELD (OpcodePrefix
),
730 BITFIELD (VexSources
),
735 BITFIELD (Broadcast
),
736 BITFIELD (StaticRounding
),
738 BITFIELD (Disp8MemShift
),
739 BITFIELD (NoDefMask
),
740 BITFIELD (ImplicitQuadGroup
),
741 BITFIELD (SwapSources
),
743 BITFIELD (ATTMnemonic
),
744 BITFIELD (ATTSyntax
),
745 BITFIELD (IntelSyntax
),
749 #define CLASS(n) #n, n
751 static const struct {
753 enum operand_class value
;
754 } operand_classes
[] = {
768 #define INSTANCE(n) #n, n
770 static const struct {
772 enum operand_instance value
;
773 } operand_instances
[] = {
782 static bitfield operand_types
[] =
791 BITFIELD (BaseIndex
),
807 BITFIELD (Unspecified
),
813 static const char *filename
;
814 static i386_cpu_flags active_cpu_flags
;
815 static int active_isstring
;
817 struct template_arg
{
818 const struct template_arg
*next
;
822 struct template_instance
{
823 const struct template_instance
*next
;
825 const struct template_arg
*args
;
828 struct template_param
{
829 const struct template_param
*next
;
834 const struct template *next
;
836 const struct template_instance
*instances
;
837 const struct template_param
*params
;
840 static const struct template *templates
;
843 compare (const void *x
, const void *y
)
845 const bitfield
*xp
= (const bitfield
*) x
;
846 const bitfield
*yp
= (const bitfield
*) y
;
847 return xp
->position
- yp
->position
;
851 fail (const char *message
, ...)
855 va_start (args
, message
);
856 fprintf (stderr
, _("%s: error: "), program_name
);
857 vfprintf (stderr
, message
, args
);
863 process_copyright (FILE *fp
)
865 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
866 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
868 This file is part of the GNU opcodes library.\n\
870 This library is free software; you can redistribute it and/or modify\n\
871 it under the terms of the GNU General Public License as published by\n\
872 the Free Software Foundation; either version 3, or (at your option)\n\
873 any later version.\n\
875 It is distributed in the hope that it will be useful, but WITHOUT\n\
876 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
877 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
878 License for more details.\n\
880 You should have received a copy of the GNU General Public License\n\
881 along with this program; if not, write to the Free Software\n\
882 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
883 MA 02110-1301, USA. */\n");
886 /* Remove leading white spaces. */
889 remove_leading_whitespaces (char *str
)
891 while (ISSPACE (*str
))
896 /* Remove trailing white spaces. */
899 remove_trailing_whitespaces (char *str
)
901 size_t last
= strlen (str
);
909 if (ISSPACE (str
[last
]))
917 /* Find next field separated by SEP and terminate it. Return a
918 pointer to the one after it. */
921 next_field (char *str
, char sep
, char **next
, char *last
)
925 p
= remove_leading_whitespaces (str
);
926 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
929 remove_trailing_whitespaces (p
);
939 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
942 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
945 char *str
, *next
, *last
;
948 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
949 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
951 /* Turn on selective bits. */
952 char *init
= xstrdup (cpu_flag_init
[i
].init
);
953 last
= init
+ strlen (init
);
954 for (next
= init
; next
&& next
< last
; )
956 str
= next_field (next
, '|', &next
, last
);
958 set_bitfield (str
, array
, 1, size
, lineno
);
968 set_bitfield (char *f
, bitfield
*array
, int value
,
969 unsigned int size
, int lineno
)
973 /* Ignore empty fields; they may result from template expansions. */
977 for (i
= 0; i
< size
; i
++)
978 if (strcasecmp (array
[i
].name
, f
) == 0)
980 array
[i
].value
= value
;
986 const char *v
= strchr (f
, '=');
993 for (i
= 0; i
< size
; i
++)
994 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
996 value
= strtol (v
+ 1, &end
, 0);
999 array
[i
].value
= value
;
1007 /* Handle CPU_XXX_FLAGS. */
1008 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
1012 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
1014 fail (_("unknown bitfield: %s\n"), f
);
1018 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
1019 int macro
, const char *comma
, const char *indent
)
1023 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
1025 fprintf (table
, "%s{ { ", indent
);
1027 for (i
= 0; i
< size
- 1; i
++)
1029 if (((i
+ 1) % 20) != 0)
1030 fprintf (table
, "%d, ", flags
[i
].value
);
1032 fprintf (table
, "%d,", flags
[i
].value
);
1033 if (((i
+ 1) % 20) == 0)
1035 /* We need \\ for macro. */
1037 fprintf (table
, " \\\n %s", indent
);
1039 fprintf (table
, "\n %s", indent
);
1042 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
1045 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
1049 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
1050 const char *comma
, const char *indent
,
1053 char *str
, *next
, *last
;
1055 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
1057 /* Copy the default cpu flags. */
1058 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
1060 if (strcasecmp (flag
, "unknown") == 0)
1062 /* We turn on everything except for cpu64 in case of
1063 CPU_UNKNOWN_FLAGS. */
1064 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1065 if (flags
[i
].position
!= Cpu64
)
1068 else if (flag
[0] == '~')
1070 last
= flag
+ strlen (flag
);
1077 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
1084 /* First we turn on everything except for cpu64. */
1085 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1086 if (flags
[i
].position
!= Cpu64
)
1089 /* Turn off selective bits. */
1090 for (; next
&& next
< last
; )
1092 str
= next_field (next
, '|', &next
, last
);
1094 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
1097 else if (strcmp (flag
, "0"))
1099 /* Turn on selective bits. */
1100 last
= flag
+ strlen (flag
);
1101 for (next
= flag
; next
&& next
< last
; )
1103 str
= next_field (next
, '|', &next
, last
);
1105 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
1109 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1114 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1118 fprintf (table
, " { ");
1120 for (i
= 0; i
< size
- 1; i
++)
1122 if (((i
+ 1) % 20) != 0)
1123 fprintf (table
, "%d, ", modifier
[i
].value
);
1125 fprintf (table
, "%d,", modifier
[i
].value
);
1126 if (((i
+ 1) % 20) == 0)
1127 fprintf (table
, "\n ");
1130 fprintf (table
, "%d },\n", modifier
[i
].value
);
1134 adjust_broadcast_modifier (char **opnd
)
1136 char *str
, *next
, *last
, *op
;
1137 int bcst_type
= INT_MAX
;
1139 /* Skip the immediate operand. */
1141 if (strcasecmp(op
, "Imm8") == 0)
1145 last
= op
+ strlen (op
);
1146 for (next
= op
; next
&& next
< last
; )
1148 str
= next_field (next
, '|', &next
, last
);
1151 if (strcasecmp(str
, "Byte") == 0)
1153 /* The smalest broadcast type, no need to check
1155 bcst_type
= BYTE_BROADCAST
;
1158 else if (strcasecmp(str
, "Word") == 0)
1160 if (bcst_type
> WORD_BROADCAST
)
1161 bcst_type
= WORD_BROADCAST
;
1163 else if (strcasecmp(str
, "Dword") == 0)
1165 if (bcst_type
> DWORD_BROADCAST
)
1166 bcst_type
= DWORD_BROADCAST
;
1168 else if (strcasecmp(str
, "Qword") == 0)
1170 if (bcst_type
> QWORD_BROADCAST
)
1171 bcst_type
= QWORD_BROADCAST
;
1177 if (bcst_type
== INT_MAX
)
1178 fail (_("unknown broadcast operand: %s\n"), op
);
1184 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
1185 unsigned int prefix
, char **opnd
, int lineno
)
1187 char *str
, *next
, *last
;
1188 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1190 active_isstring
= 0;
1192 /* Copy the default opcode modifier. */
1193 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1195 if (strcmp (mod
, "0"))
1197 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1199 last
= mod
+ strlen (mod
);
1200 for (next
= mod
; next
&& next
< last
; )
1202 str
= next_field (next
, '|', &next
, last
);
1206 if (strcasecmp(str
, "Broadcast") == 0)
1207 val
= adjust_broadcast_modifier (opnd
);
1209 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1211 if (strcasecmp(str
, "IsString") == 0)
1212 active_isstring
= 1;
1214 if (strcasecmp(str
, "W") == 0)
1217 if (strcasecmp(str
, "No_bSuf") == 0)
1219 if (strcasecmp(str
, "No_wSuf") == 0)
1221 if (strcasecmp(str
, "No_lSuf") == 0)
1223 if (strcasecmp(str
, "No_qSuf") == 0)
1230 if (!modifiers
[OpcodeSpace
].value
)
1231 modifiers
[OpcodeSpace
].value
= space
;
1232 else if (modifiers
[OpcodeSpace
].value
!= space
)
1233 fail (_("%s:%d: Conflicting opcode space specifications\n"),
1237 _("%s:%d: Warning: redundant opcode space specification\n"),
1243 if (!modifiers
[OpcodePrefix
].value
)
1244 modifiers
[OpcodePrefix
].value
= prefix
;
1245 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1246 fail (_("%s:%d: Conflicting prefix specifications\n"),
1250 _("%s:%d: Warning: redundant prefix specification\n"),
1254 if (have_w
&& !bwlq_suf
)
1255 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1256 if (have_w
&& !(bwlq_suf
& 1))
1257 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1259 if (have_w
&& !(bwlq_suf
& ~1))
1261 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1264 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1274 output_operand_type (FILE *table
, enum operand_class
class,
1275 enum operand_instance instance
,
1276 const bitfield
*types
, unsigned int size
,
1277 enum stage stage
, const char *indent
)
1281 fprintf (table
, "{ { %d, %d, ", class, instance
);
1283 for (i
= 0; i
< size
- 1; i
++)
1285 if (((i
+ 3) % 20) != 0)
1286 fprintf (table
, "%d, ", types
[i
].value
);
1288 fprintf (table
, "%d,", types
[i
].value
);
1289 if (((i
+ 3) % 20) == 0)
1291 /* We need \\ for macro. */
1292 if (stage
== stage_macros
)
1293 fprintf (table
, " \\\n%s", indent
);
1295 fprintf (table
, "\n%s", indent
);
1299 fprintf (table
, "%d } }", types
[i
].value
);
1303 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1304 const char *indent
, int lineno
)
1306 char *str
, *next
, *last
;
1307 enum operand_class
class = ClassNone
;
1308 enum operand_instance instance
= InstanceNone
;
1309 bitfield types
[ARRAY_SIZE (operand_types
)];
1311 /* Copy the default operand type. */
1312 memcpy (types
, operand_types
, sizeof (types
));
1314 if (strcmp (op
, "0"))
1318 last
= op
+ strlen (op
);
1319 for (next
= op
; next
&& next
< last
; )
1321 str
= next_field (next
, '|', &next
, last
);
1326 if (!strncmp(str
, "Class=", 6))
1328 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1329 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1331 class = operand_classes
[i
].value
;
1337 if (str
&& !strncmp(str
, "Instance=", 9))
1339 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1340 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1342 instance
= operand_instances
[i
].value
;
1350 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1351 if (strcasecmp(str
, "BaseIndex") == 0)
1356 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1358 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1359 if (!active_cpu_flags
.bitfield
.cpu64
1360 && !active_cpu_flags
.bitfield
.cpumpx
)
1361 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1362 if (!active_cpu_flags
.bitfield
.cpu64
)
1363 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1364 if (!active_cpu_flags
.bitfield
.cpuno64
)
1365 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1368 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1373 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1374 char *last
, int lineno
)
1376 unsigned int i
, length
, prefix
= 0, space
= 0;
1377 char *base_opcode
, *extension_opcode
, *end
;
1378 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1379 unsigned long long opcode
;
1381 /* Find base_opcode. */
1382 base_opcode
= next_field (str
, ',', &str
, last
);
1384 /* Find extension_opcode. */
1385 extension_opcode
= next_field (str
, ',', &str
, last
);
1387 /* Find cpu_flags. */
1388 cpu_flags
= next_field (str
, ',', &str
, last
);
1390 /* Find opcode_modifier. */
1391 opcode_modifier
= next_field (str
, ',', &str
, last
);
1393 /* Remove the first {. */
1394 str
= remove_leading_whitespaces (str
);
1397 str
= remove_leading_whitespaces (str
+ 1);
1398 remove_trailing_whitespaces (str
);
1400 /* Remove } and trailing white space. */
1402 if (!i
|| str
[i
- 1] != '}')
1405 remove_trailing_whitespaces (str
);
1408 operand_types
[i
= 0] = NULL
;
1411 last
= str
+ strlen (str
);
1413 /* Find operand_types. */
1414 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1418 operand_types
[i
] = NULL
;
1422 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1426 opcode
= strtoull (base_opcode
, &end
, 0);
1428 /* Determine opcode length. */
1429 for (length
= 1; length
< 8; ++length
)
1430 if (!(opcode
>> (8 * length
)))
1433 /* Transform prefixes encoded in the opcode into opcode modifier
1437 switch (opcode
>> (8 * length
- 8))
1439 case 0x66: prefix
= PREFIX_0X66
; break;
1440 case 0xF3: prefix
= PREFIX_0XF3
; break;
1441 case 0xF2: prefix
= PREFIX_0XF2
; break;
1445 opcode
&= (1ULL << (8 * --length
)) - 1;
1448 /* Transform opcode space encoded in the opcode into opcode modifier
1450 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1452 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1454 default: space
= SPACE_0F
; break;
1455 case 0x38: space
= SPACE_0F38
; break;
1456 case 0x3A: space
= SPACE_0F3A
; break;
1459 if (space
!= SPACE_0F
&& --length
== 1)
1460 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1461 filename
, lineno
, name
);
1462 opcode
&= (1ULL << (8 * --length
)) - 1;
1466 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1467 filename
, lineno
, name
, 2 * length
, opcode
);
1469 fprintf (table
, " { \"%s\", 0x%0*llx%s, %s, %lu,\n",
1470 name
, 2 * (int)length
, opcode
, end
, extension_opcode
, i
);
1472 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1473 operand_types
, lineno
);
1475 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1477 fprintf (table
, " { ");
1479 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1481 if (!operand_types
[i
])
1484 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1490 fprintf (table
, ",\n ");
1492 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1495 fprintf (table
, " } },\n");
1498 struct opcode_hash_entry
1500 struct opcode_hash_entry
*next
;
1506 /* Calculate the hash value of an opcode hash entry P. */
1509 opcode_hash_hash (const void *p
)
1511 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1512 return htab_hash_string (entry
->name
);
1515 /* Compare a string Q against an opcode hash entry P. */
1518 opcode_hash_eq (const void *p
, const void *q
)
1520 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1521 const char *name
= (const char *) q
;
1522 return strcmp (name
, entry
->name
) == 0;
1526 parse_template (char *buf
, int lineno
)
1528 char sep
, *end
, *name
;
1529 struct template *tmpl
= xmalloc (sizeof (*tmpl
));
1530 struct template_instance
*last_inst
= NULL
;
1532 buf
= remove_leading_whitespaces (buf
+ 1);
1533 end
= strchr (buf
, ':');
1535 fail ("%s: %d: missing ':'\n", filename
, lineno
);
1537 remove_trailing_whitespaces (buf
);
1540 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1541 tmpl
->name
= xstrdup (buf
);
1543 tmpl
->params
= NULL
;
1545 struct template_param
*param
;
1547 buf
= remove_leading_whitespaces (end
);
1548 end
= strpbrk (buf
, ":,");
1550 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1554 remove_trailing_whitespaces (buf
);
1556 param
= xmalloc (sizeof (*param
));
1557 param
->name
= xstrdup (buf
);
1558 param
->next
= tmpl
->params
;
1559 tmpl
->params
= param
;
1560 } while (sep
== ':');
1562 tmpl
->instances
= NULL
;
1564 struct template_instance
*inst
;
1566 const struct template_param
*param
;
1568 buf
= remove_leading_whitespaces (end
);
1569 end
= strpbrk (buf
, ",>");
1571 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1576 inst
= xmalloc (sizeof (*inst
));
1580 cur
= next_field (buf
, ':', &next
, end
);
1581 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1583 for (param
= tmpl
->params
; param
; param
= param
->next
)
1585 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1587 cur
= next_field (next
, ':', &next
, end
);
1589 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1590 arg
->val
= xstrdup (cur
);
1591 arg
->next
= inst
->args
;
1595 if (tmpl
->instances
)
1596 last_inst
->next
= inst
;
1598 tmpl
->instances
= inst
;
1600 } while (sep
== ',');
1602 buf
= remove_leading_whitespaces (end
);
1604 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1605 filename
, lineno
, buf
);
1607 tmpl
->next
= templates
;
1612 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1613 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1615 static unsigned int idx
, opcode_array_size
;
1616 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1617 struct opcode_hash_entry
**hash_slot
, **entry
;
1618 char *ptr1
= strchr(name
, '<'), *ptr2
;
1622 /* Get the slot in hash table. */
1623 hash_slot
= (struct opcode_hash_entry
**)
1624 htab_find_slot_with_hash (opcode_hash_table
, name
,
1625 htab_hash_string (name
),
1628 if (*hash_slot
== NULL
)
1630 /* It is the new one. Put it on opcode array. */
1631 if (idx
>= opcode_array_size
)
1633 /* Grow the opcode array when needed. */
1634 opcode_array_size
+= 1024;
1635 opcode_array
= (struct opcode_hash_entry
**)
1636 xrealloc (opcode_array
,
1637 sizeof (*opcode_array
) * opcode_array_size
);
1638 *opcode_array_p
= opcode_array
;
1641 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1642 xmalloc (sizeof (struct opcode_hash_entry
));
1643 opcode_array
[idx
]->next
= NULL
;
1644 opcode_array
[idx
]->name
= xstrdup (name
);
1645 opcode_array
[idx
]->opcode
= xstrdup (str
);
1646 opcode_array
[idx
]->lineno
= lineno
;
1647 *hash_slot
= opcode_array
[idx
];
1652 /* Append it to the existing one. */
1654 while ((*entry
) != NULL
)
1655 entry
= &(*entry
)->next
;
1656 *entry
= (struct opcode_hash_entry
*)
1657 xmalloc (sizeof (struct opcode_hash_entry
));
1658 (*entry
)->next
= NULL
;
1659 (*entry
)->name
= (*hash_slot
)->name
;
1660 (*entry
)->opcode
= xstrdup (str
);
1661 (*entry
)->lineno
= lineno
;
1664 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1665 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1668 const struct template *tmpl
;
1669 const struct template_instance
*inst
;
1672 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1673 remove_trailing_whitespaces (ptr1
);
1677 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1678 if (!strcmp(ptr1
, tmpl
->name
))
1681 fail ("reference to unknown template '%s'\n", ptr1
);
1683 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1685 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1686 char *str2
= xmalloc(2 * strlen(str
));
1689 strcpy (name2
, name
);
1690 strcat (name2
, inst
->name
);
1691 strcat (name2
, ptr2
);
1693 for (ptr1
= str2
, src
= str
; *src
; )
1695 const char *ident
= tmpl
->name
, *end
;
1696 const struct template_param
*param
;
1697 const struct template_arg
*arg
;
1699 if ((*ptr1
= *src
++) != '<')
1704 while (ISSPACE(*src
))
1706 while (*ident
&& *src
== *ident
)
1708 while (ISSPACE(*src
))
1710 if (*src
!= ':' || *ident
!= '\0')
1712 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1713 ptr1
+= ident
- tmpl
->name
;
1716 while (ISSPACE(*++src
))
1720 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1723 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1724 param
= param
->next
, arg
= arg
->next
)
1726 if (end
- src
== strlen (param
->name
)
1727 && !memcmp (src
, param
->name
, end
- src
))
1735 fail ("template '%s' has no parameter '%.*s'\n",
1736 tmpl
->name
, (int)(end
- src
), src
);
1738 while (ISSPACE(*src
))
1741 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1743 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1744 ptr1
+= strlen(arg
->val
);
1750 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1762 process_i386_opcodes (FILE *table
)
1767 char *str
, *p
, *last
, *name
;
1768 htab_t opcode_hash_table
;
1769 struct opcode_hash_entry
**opcode_array
= NULL
;
1770 int lineno
= 0, marker
= 0;
1772 filename
= "i386-opc.tbl";
1776 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1777 opcode_hash_eq
, NULL
,
1780 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1781 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1783 /* Put everything on opcode array. */
1786 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1791 p
= remove_leading_whitespaces (buf
);
1793 /* Skip comments. */
1794 str
= strstr (p
, "//");
1798 /* Remove trailing white spaces. */
1799 remove_trailing_whitespaces (p
);
1804 if (!strcmp("### MARKER ###", buf
))
1808 /* Since we ignore all included files (we only care about their
1809 #define-s here), we don't need to monitor filenames. The final
1810 line number directive is going to refer to the main source file
1815 p
= remove_leading_whitespaces (p
+ 1);
1816 if (!strncmp(p
, "line", 4))
1818 ln
= strtoul (p
, &end
, 10);
1819 if (ln
> 1 && ln
< INT_MAX
1820 && *remove_leading_whitespaces (end
) == '"')
1823 /* Ignore comments. */
1828 parse_template (p
, lineno
);
1836 last
= p
+ strlen (p
);
1839 name
= next_field (p
, ',', &str
, last
);
1841 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1845 /* Process opcode array. */
1846 for (j
= 0; j
< i
; j
++)
1848 struct opcode_hash_entry
*next
;
1850 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1854 lineno
= next
->lineno
;
1855 last
= str
+ strlen (str
);
1856 output_i386_opcode (table
, name
, str
, last
, lineno
);
1862 fprintf (table
, " { NULL, 0, 0, 0,\n");
1864 process_i386_opcode_modifier (table
, "0", 0, 0, NULL
, -1);
1866 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1868 fprintf (table
, " { ");
1869 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1870 fprintf (table
, " } }\n");
1872 fprintf (table
, "};\n");
1876 process_i386_registers (FILE *table
)
1880 char *str
, *p
, *last
;
1881 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1882 char *dw2_32_num
, *dw2_64_num
;
1885 filename
= "i386-reg.tbl";
1886 fp
= fopen (filename
, "r");
1888 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1891 fprintf (table
, "\n/* i386 register table. */\n\n");
1892 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1896 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1901 p
= remove_leading_whitespaces (buf
);
1903 /* Skip comments. */
1904 str
= strstr (p
, "//");
1908 /* Remove trailing white spaces. */
1909 remove_trailing_whitespaces (p
);
1914 fprintf (table
, "%s\n", p
);
1922 last
= p
+ strlen (p
);
1924 /* Find reg_name. */
1925 reg_name
= next_field (p
, ',', &str
, last
);
1927 /* Find reg_type. */
1928 reg_type
= next_field (str
, ',', &str
, last
);
1930 /* Find reg_flags. */
1931 reg_flags
= next_field (str
, ',', &str
, last
);
1934 reg_num
= next_field (str
, ',', &str
, last
);
1936 fprintf (table
, " { \"%s\",\n ", reg_name
);
1938 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1941 /* Find 32-bit Dwarf2 register number. */
1942 dw2_32_num
= next_field (str
, ',', &str
, last
);
1944 /* Find 64-bit Dwarf2 register number. */
1945 dw2_64_num
= next_field (str
, ',', &str
, last
);
1947 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1948 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1953 fprintf (table
, "};\n");
1955 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1959 process_i386_initializers (void)
1962 FILE *fp
= fopen ("i386-init.h", "w");
1966 fail (_("can't create i386-init.h, errno = %s\n"),
1969 process_copyright (fp
);
1971 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1973 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1974 init
= xstrdup (cpu_flag_init
[i
].init
);
1975 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1979 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1981 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1982 init
= xstrdup (operand_type_init
[i
].init
);
1983 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1991 /* Program options. */
1992 #define OPTION_SRCDIR 200
1994 struct option long_options
[] =
1996 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1997 {"debug", no_argument
, NULL
, 'd'},
1998 {"version", no_argument
, NULL
, 'V'},
1999 {"help", no_argument
, NULL
, 'h'},
2000 {0, no_argument
, NULL
, 0}
2004 print_version (void)
2006 printf ("%s: version 1.0\n", program_name
);
2011 usage (FILE * stream
, int status
)
2013 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2019 main (int argc
, char **argv
)
2021 extern int chdir (char *);
2022 char *srcdir
= NULL
;
2024 unsigned int i
, cpumax
;
2027 program_name
= *argv
;
2028 xmalloc_set_program_name (program_name
);
2030 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2055 if (chdir (srcdir
) != 0)
2056 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2057 srcdir
, xstrerror (errno
));
2059 /* cpu_flags isn't sorted by position. */
2061 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2062 if (cpu_flags
[i
].position
> cpumax
)
2063 cpumax
= cpu_flags
[i
].position
;
2065 /* Check the unused bitfield in i386_cpu_flags. */
2067 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2069 if ((cpumax
- 1) != CpuMax
)
2070 fail (_("CpuMax != %d!\n"), cpumax
);
2072 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2074 if (cpumax
!= CpuMax
)
2075 fail (_("CpuMax != %d!\n"), cpumax
);
2077 c
= CpuNumOfBits
- CpuMax
- 1;
2079 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2082 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2084 /* Check the unused bitfield in i386_operand_type. */
2086 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2089 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2092 c
= OTNumOfBits
- OTNum
;
2094 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2097 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2100 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2101 sizeof (opcode_modifiers
[0]), compare
);
2103 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2104 sizeof (operand_types
[0]), compare
);
2106 table
= fopen ("i386-tbl.h", "w");
2108 fail (_("can't create i386-tbl.h, errno = %s\n"),
2111 process_copyright (table
);
2113 process_i386_opcodes (table
);
2114 process_i386_registers (table
);
2115 process_i386_initializers ();