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_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" },
249 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
252 { "CPU_RDSEED_FLAGS",
254 { "CPU_PRFCHW_FLAGS",
259 "CPU_XSAVE_FLAGS|CpuMPX" },
261 "CPU_SSE2_FLAGS|CpuSHA" },
262 { "CPU_CLFLUSHOPT_FLAGS",
264 { "CPU_XSAVES_FLAGS",
265 "CPU_XSAVE_FLAGS|CpuXSAVES" },
266 { "CPU_XSAVEC_FLAGS",
267 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
268 { "CPU_PREFETCHWT1_FLAGS",
274 { "CPU_CLZERO_FLAGS",
276 { "CPU_MWAITX_FLAGS",
279 "CPU_XSAVE_FLAGS|CpuOSPKE" },
282 { "CPU_PTWRITE_FLAGS",
292 { "CPU_VPCLMULQDQ_FLAGS",
294 { "CPU_WBNOINVD_FLAGS",
296 { "CPU_PCONFIG_FLAGS",
298 { "CPU_WAITPKG_FLAGS",
302 { "CPU_CLDEMOTE_FLAGS",
304 { "CPU_AMX_INT8_FLAGS",
306 { "CPU_AMX_BF16_FLAGS",
308 { "CPU_AMX_TILE_FLAGS",
310 { "CPU_MOVDIRI_FLAGS",
312 { "CPU_MOVDIR64B_FLAGS",
314 { "CPU_ENQCMD_FLAGS",
316 { "CPU_SERIALIZE_FLAGS",
318 { "CPU_AVX512_VP2INTERSECT_FLAGS",
319 "CpuAVX512_VP2INTERSECT" },
324 { "CPU_MCOMMIT_FLAGS",
326 { "CPU_SEV_ES_FLAGS",
328 { "CPU_TSXLDTRK_FLAGS",
332 { "CPU_WIDEKL_FLAGS",
334 { "CPU_HRESET_FLAGS",
336 { "CPU_INVLPGB_FLAGS",
338 { "CPU_TLBSYNC_FLAGS",
342 { "CPU_ANY_X87_FLAGS",
343 "CPU_ANY_287_FLAGS|Cpu8087" },
344 { "CPU_ANY_287_FLAGS",
345 "CPU_ANY_387_FLAGS|Cpu287" },
346 { "CPU_ANY_387_FLAGS",
347 "CPU_ANY_687_FLAGS|Cpu387" },
348 { "CPU_ANY_687_FLAGS",
349 "Cpu687|CpuFISTTP" },
350 { "CPU_ANY_CMOV_FLAGS",
352 { "CPU_ANY_FXSR_FLAGS",
354 { "CPU_ANY_MMX_FLAGS",
355 "CPU_3DNOWA_FLAGS" },
356 { "CPU_ANY_SSE_FLAGS",
357 "CPU_ANY_SSE2_FLAGS|CpuSSE" },
358 { "CPU_ANY_SSE2_FLAGS",
359 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
360 { "CPU_ANY_SSE3_FLAGS",
361 "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
362 { "CPU_ANY_SSSE3_FLAGS",
363 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
364 { "CPU_ANY_SSE4_1_FLAGS",
365 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
366 { "CPU_ANY_SSE4_2_FLAGS",
368 { "CPU_ANY_SSE4A_FLAGS",
370 { "CPU_ANY_AVX_FLAGS",
371 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
372 { "CPU_ANY_AVX2_FLAGS",
373 "CPU_ANY_AVX512F_FLAGS|CpuAVX2" },
374 { "CPU_ANY_AVX512F_FLAGS",
375 "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" },
376 { "CPU_ANY_AVX512CD_FLAGS",
378 { "CPU_ANY_AVX512ER_FLAGS",
380 { "CPU_ANY_AVX512PF_FLAGS",
382 { "CPU_ANY_AVX512DQ_FLAGS",
384 { "CPU_ANY_AVX512BW_FLAGS",
385 "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
386 { "CPU_ANY_AVX512VL_FLAGS",
388 { "CPU_ANY_AVX512IFMA_FLAGS",
390 { "CPU_ANY_AVX512VBMI_FLAGS",
392 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
393 "CpuAVX512_4FMAPS" },
394 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
395 "CpuAVX512_4VNNIW" },
396 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
397 "CpuAVX512_VPOPCNTDQ" },
398 { "CPU_ANY_IBT_FLAGS",
400 { "CPU_ANY_SHSTK_FLAGS",
402 { "CPU_ANY_AVX512_VBMI2_FLAGS",
404 { "CPU_ANY_AVX512_VNNI_FLAGS",
406 { "CPU_ANY_AVX512_BITALG_FLAGS",
407 "CpuAVX512_BITALG" },
408 { "CPU_ANY_AVX512_BF16_FLAGS",
410 { "CPU_ANY_AMX_INT8_FLAGS",
412 { "CPU_ANY_AMX_BF16_FLAGS",
414 { "CPU_ANY_AMX_TILE_FLAGS",
415 "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16" },
416 { "CPU_ANY_AVX_VNNI_FLAGS",
418 { "CPU_ANY_MOVDIRI_FLAGS",
420 { "CPU_ANY_UINTR_FLAGS",
422 { "CPU_ANY_MOVDIR64B_FLAGS",
424 { "CPU_ANY_ENQCMD_FLAGS",
426 { "CPU_ANY_SERIALIZE_FLAGS",
428 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
429 "CpuAVX512_VP2INTERSECT" },
430 { "CPU_ANY_TDX_FLAGS",
432 { "CPU_ANY_TSXLDTRK_FLAGS",
434 { "CPU_ANY_KL_FLAGS",
436 { "CPU_ANY_WIDEKL_FLAGS",
438 { "CPU_ANY_HRESET_FLAGS",
440 { "CPU_ANY_AVX512_FP16_FLAGS",
444 static initializer operand_type_init
[] =
446 { "OPERAND_TYPE_NONE",
448 { "OPERAND_TYPE_REG8",
450 { "OPERAND_TYPE_REG16",
452 { "OPERAND_TYPE_REG32",
454 { "OPERAND_TYPE_REG64",
456 { "OPERAND_TYPE_IMM1",
458 { "OPERAND_TYPE_IMM8",
460 { "OPERAND_TYPE_IMM8S",
462 { "OPERAND_TYPE_IMM16",
464 { "OPERAND_TYPE_IMM32",
466 { "OPERAND_TYPE_IMM32S",
468 { "OPERAND_TYPE_IMM64",
470 { "OPERAND_TYPE_BASEINDEX",
472 { "OPERAND_TYPE_DISP8",
474 { "OPERAND_TYPE_DISP16",
476 { "OPERAND_TYPE_DISP32",
478 { "OPERAND_TYPE_DISP32S",
480 { "OPERAND_TYPE_DISP64",
482 { "OPERAND_TYPE_INOUTPORTREG",
483 "Instance=RegD|Word" },
484 { "OPERAND_TYPE_SHIFTCOUNT",
485 "Instance=RegC|Byte" },
486 { "OPERAND_TYPE_CONTROL",
488 { "OPERAND_TYPE_TEST",
490 { "OPERAND_TYPE_DEBUG",
492 { "OPERAND_TYPE_FLOATREG",
494 { "OPERAND_TYPE_FLOATACC",
495 "Instance=Accum|Tbyte" },
496 { "OPERAND_TYPE_SREG",
498 { "OPERAND_TYPE_REGMMX",
500 { "OPERAND_TYPE_REGXMM",
501 "Class=RegSIMD|Xmmword" },
502 { "OPERAND_TYPE_REGYMM",
503 "Class=RegSIMD|Ymmword" },
504 { "OPERAND_TYPE_REGZMM",
505 "Class=RegSIMD|Zmmword" },
506 { "OPERAND_TYPE_REGTMM",
507 "Class=RegSIMD|Tmmword" },
508 { "OPERAND_TYPE_REGMASK",
510 { "OPERAND_TYPE_REGBND",
512 { "OPERAND_TYPE_ACC8",
513 "Instance=Accum|Byte" },
514 { "OPERAND_TYPE_ACC16",
515 "Instance=Accum|Word" },
516 { "OPERAND_TYPE_ACC32",
517 "Instance=Accum|Dword" },
518 { "OPERAND_TYPE_ACC64",
519 "Instance=Accum|Qword" },
520 { "OPERAND_TYPE_DISP16_32",
522 { "OPERAND_TYPE_ANYDISP",
523 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
524 { "OPERAND_TYPE_IMM16_32",
526 { "OPERAND_TYPE_IMM16_32S",
528 { "OPERAND_TYPE_IMM16_32_32S",
529 "Imm16|Imm32|Imm32S" },
530 { "OPERAND_TYPE_IMM32_64",
532 { "OPERAND_TYPE_IMM32_32S_DISP32",
533 "Imm32|Imm32S|Disp32" },
534 { "OPERAND_TYPE_IMM64_DISP64",
536 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
537 "Imm32|Imm32S|Imm64|Disp32" },
538 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
539 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
540 { "OPERAND_TYPE_ANYIMM",
541 "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
544 typedef struct bitfield
551 #define BITFIELD(n) { n, 0, #n }
553 static bitfield cpu_flags
[] =
563 BITFIELD (CpuClflush
),
565 BITFIELD (CpuSYSCALL
),
570 BITFIELD (CpuFISTTP
),
576 BITFIELD (CpuSSE4_1
),
577 BITFIELD (CpuSSE4_2
),
580 BITFIELD (CpuAVX512F
),
581 BITFIELD (CpuAVX512CD
),
582 BITFIELD (CpuAVX512ER
),
583 BITFIELD (CpuAVX512PF
),
584 BITFIELD (CpuAVX512VL
),
585 BITFIELD (CpuAVX512DQ
),
586 BITFIELD (CpuAVX512BW
),
590 BITFIELD (Cpu3dnowA
),
591 BITFIELD (CpuPadLock
),
596 BITFIELD (CpuXsaveopt
),
598 BITFIELD (CpuPCLMUL
),
609 BITFIELD (CpuRdtscp
),
610 BITFIELD (CpuFSGSBase
),
615 BITFIELD (CpuPOPCNT
),
618 BITFIELD (CpuINVPCID
),
619 BITFIELD (CpuVMFUNC
),
620 BITFIELD (CpuRDSEED
),
622 BITFIELD (CpuPRFCHW
),
625 BITFIELD (CpuClflushOpt
),
626 BITFIELD (CpuXSAVES
),
627 BITFIELD (CpuXSAVEC
),
628 BITFIELD (CpuPREFETCHWT1
),
632 BITFIELD (CpuAVX512IFMA
),
633 BITFIELD (CpuAVX512VBMI
),
634 BITFIELD (CpuAVX512_4FMAPS
),
635 BITFIELD (CpuAVX512_4VNNIW
),
636 BITFIELD (CpuAVX512_VPOPCNTDQ
),
637 BITFIELD (CpuAVX512_VBMI2
),
638 BITFIELD (CpuAVX512_VNNI
),
639 BITFIELD (CpuAVX512_BITALG
),
640 BITFIELD (CpuAVX512_BF16
),
641 BITFIELD (CpuAVX512_VP2INTERSECT
),
643 BITFIELD (CpuAVX_VNNI
),
644 BITFIELD (CpuAVX512_FP16
),
645 BITFIELD (CpuMWAITX
),
646 BITFIELD (CpuCLZERO
),
649 BITFIELD (CpuPTWRITE
),
654 BITFIELD (CpuVPCLMULQDQ
),
655 BITFIELD (CpuWBNOINVD
),
656 BITFIELD (CpuPCONFIG
),
657 BITFIELD (CpuWAITPKG
),
659 BITFIELD (CpuCLDEMOTE
),
660 BITFIELD (CpuAMX_INT8
),
661 BITFIELD (CpuAMX_BF16
),
662 BITFIELD (CpuAMX_TILE
),
663 BITFIELD (CpuMOVDIRI
),
664 BITFIELD (CpuMOVDIR64B
),
665 BITFIELD (CpuENQCMD
),
666 BITFIELD (CpuSERIALIZE
),
668 BITFIELD (CpuMCOMMIT
),
669 BITFIELD (CpuSEV_ES
),
670 BITFIELD (CpuTSXLDTRK
),
672 BITFIELD (CpuWideKL
),
673 BITFIELD (CpuHRESET
),
674 BITFIELD (CpuINVLPGB
),
675 BITFIELD (CpuTLBSYNC
),
680 BITFIELD (CpuUnused
),
684 static bitfield opcode_modifiers
[] =
694 BITFIELD (CheckRegSize
),
695 BITFIELD (DistinctDest
),
696 BITFIELD (MnemonicSize
),
707 BITFIELD (BNDPrefixOk
),
708 BITFIELD (RegKludge
),
709 BITFIELD (Implicit1stXmm0
),
713 BITFIELD (AddrPrefixOpReg
),
718 BITFIELD (PseudoVexPrefix
),
722 BITFIELD (OpcodeSpace
),
723 BITFIELD (OpcodePrefix
),
724 BITFIELD (VexSources
),
729 BITFIELD (Broadcast
),
730 BITFIELD (StaticRounding
),
732 BITFIELD (Disp8MemShift
),
733 BITFIELD (NoDefMask
),
734 BITFIELD (ImplicitQuadGroup
),
735 BITFIELD (SwapSources
),
737 BITFIELD (ATTMnemonic
),
738 BITFIELD (ATTSyntax
),
739 BITFIELD (IntelSyntax
),
743 #define CLASS(n) #n, n
745 static const struct {
747 enum operand_class value
;
748 } operand_classes
[] = {
762 #define INSTANCE(n) #n, n
764 static const struct {
766 enum operand_instance value
;
767 } operand_instances
[] = {
776 static bitfield operand_types
[] =
785 BITFIELD (BaseIndex
),
801 BITFIELD (Unspecified
),
807 static const char *filename
;
808 static i386_cpu_flags active_cpu_flags
;
809 static int active_isstring
;
811 struct template_arg
{
812 const struct template_arg
*next
;
816 struct template_instance
{
817 const struct template_instance
*next
;
819 const struct template_arg
*args
;
822 struct template_param
{
823 const struct template_param
*next
;
828 const struct template *next
;
830 const struct template_instance
*instances
;
831 const struct template_param
*params
;
834 static const struct template *templates
;
837 compare (const void *x
, const void *y
)
839 const bitfield
*xp
= (const bitfield
*) x
;
840 const bitfield
*yp
= (const bitfield
*) y
;
841 return xp
->position
- yp
->position
;
845 fail (const char *message
, ...)
849 va_start (args
, message
);
850 fprintf (stderr
, _("%s: error: "), program_name
);
851 vfprintf (stderr
, message
, args
);
857 process_copyright (FILE *fp
)
859 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
860 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
862 This file is part of the GNU opcodes library.\n\
864 This library is free software; you can redistribute it and/or modify\n\
865 it under the terms of the GNU General Public License as published by\n\
866 the Free Software Foundation; either version 3, or (at your option)\n\
867 any later version.\n\
869 It is distributed in the hope that it will be useful, but WITHOUT\n\
870 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
871 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
872 License for more details.\n\
874 You should have received a copy of the GNU General Public License\n\
875 along with this program; if not, write to the Free Software\n\
876 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
877 MA 02110-1301, USA. */\n");
880 /* Remove leading white spaces. */
883 remove_leading_whitespaces (char *str
)
885 while (ISSPACE (*str
))
890 /* Remove trailing white spaces. */
893 remove_trailing_whitespaces (char *str
)
895 size_t last
= strlen (str
);
903 if (ISSPACE (str
[last
]))
911 /* Find next field separated by SEP and terminate it. Return a
912 pointer to the one after it. */
915 next_field (char *str
, char sep
, char **next
, char *last
)
919 p
= remove_leading_whitespaces (str
);
920 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
923 remove_trailing_whitespaces (p
);
933 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
936 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
939 char *str
, *next
, *last
;
942 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
943 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
945 /* Turn on selective bits. */
946 char *init
= xstrdup (cpu_flag_init
[i
].init
);
947 last
= init
+ strlen (init
);
948 for (next
= init
; next
&& next
< last
; )
950 str
= next_field (next
, '|', &next
, last
);
952 set_bitfield (str
, array
, 1, size
, lineno
);
962 set_bitfield (char *f
, bitfield
*array
, int value
,
963 unsigned int size
, int lineno
)
967 /* Ignore empty fields; they may result from template expansions. */
971 for (i
= 0; i
< size
; i
++)
972 if (strcasecmp (array
[i
].name
, f
) == 0)
974 array
[i
].value
= value
;
980 const char *v
= strchr (f
, '=');
987 for (i
= 0; i
< size
; i
++)
988 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
990 value
= strtol (v
+ 1, &end
, 0);
993 array
[i
].value
= value
;
1001 /* Handle CPU_XXX_FLAGS. */
1002 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
1006 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
1008 fail (_("unknown bitfield: %s\n"), f
);
1012 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
1013 int macro
, const char *comma
, const char *indent
)
1017 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
1019 fprintf (table
, "%s{ { ", indent
);
1021 for (i
= 0; i
< size
- 1; i
++)
1023 if (((i
+ 1) % 20) != 0)
1024 fprintf (table
, "%d, ", flags
[i
].value
);
1026 fprintf (table
, "%d,", flags
[i
].value
);
1027 if (((i
+ 1) % 20) == 0)
1029 /* We need \\ for macro. */
1031 fprintf (table
, " \\\n %s", indent
);
1033 fprintf (table
, "\n %s", indent
);
1036 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
1039 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
1043 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
1044 const char *comma
, const char *indent
,
1047 char *str
, *next
= flag
, *last
;
1050 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
1052 /* Copy the default cpu flags. */
1053 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
1057 last
= flag
+ strlen (flag
);
1064 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
1071 /* First we turn on everything except for cpu64, cpuno64, and - if
1072 present - the padding field. */
1073 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1074 if (flags
[i
].position
< Cpu64
)
1077 /* Turn off selective bits. */
1081 if (strcmp (flag
, "0"))
1083 /* Turn on/off selective bits. */
1084 last
= flag
+ strlen (flag
);
1085 for (; next
&& next
< last
; )
1087 str
= next_field (next
, '|', &next
, last
);
1089 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
1093 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1098 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1102 fprintf (table
, " { ");
1104 for (i
= 0; i
< size
- 1; i
++)
1106 if (((i
+ 1) % 20) != 0)
1107 fprintf (table
, "%d, ", modifier
[i
].value
);
1109 fprintf (table
, "%d,", modifier
[i
].value
);
1110 if (((i
+ 1) % 20) == 0)
1111 fprintf (table
, "\n ");
1114 fprintf (table
, "%d },\n", modifier
[i
].value
);
1118 adjust_broadcast_modifier (char **opnd
)
1120 char *str
, *next
, *last
, *op
;
1121 int bcst_type
= INT_MAX
;
1123 /* Skip the immediate operand. */
1125 if (strcasecmp(op
, "Imm8") == 0)
1129 last
= op
+ strlen (op
);
1130 for (next
= op
; next
&& next
< last
; )
1132 str
= next_field (next
, '|', &next
, last
);
1135 if (strcasecmp(str
, "Byte") == 0)
1137 /* The smalest broadcast type, no need to check
1139 bcst_type
= BYTE_BROADCAST
;
1142 else if (strcasecmp(str
, "Word") == 0)
1144 if (bcst_type
> WORD_BROADCAST
)
1145 bcst_type
= WORD_BROADCAST
;
1147 else if (strcasecmp(str
, "Dword") == 0)
1149 if (bcst_type
> DWORD_BROADCAST
)
1150 bcst_type
= DWORD_BROADCAST
;
1152 else if (strcasecmp(str
, "Qword") == 0)
1154 if (bcst_type
> QWORD_BROADCAST
)
1155 bcst_type
= QWORD_BROADCAST
;
1161 if (bcst_type
== INT_MAX
)
1162 fail (_("unknown broadcast operand: %s\n"), op
);
1168 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
1169 unsigned int prefix
, char **opnd
, int lineno
)
1171 char *str
, *next
, *last
;
1172 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1174 active_isstring
= 0;
1176 /* Copy the default opcode modifier. */
1177 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1179 if (strcmp (mod
, "0"))
1181 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1183 last
= mod
+ strlen (mod
);
1184 for (next
= mod
; next
&& next
< last
; )
1186 str
= next_field (next
, '|', &next
, last
);
1190 if (strcasecmp(str
, "Broadcast") == 0)
1191 val
= adjust_broadcast_modifier (opnd
);
1193 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1195 if (strcasecmp(str
, "IsString") == 0)
1196 active_isstring
= 1;
1198 if (strcasecmp(str
, "W") == 0)
1201 if (strcasecmp(str
, "No_bSuf") == 0)
1203 if (strcasecmp(str
, "No_wSuf") == 0)
1205 if (strcasecmp(str
, "No_lSuf") == 0)
1207 if (strcasecmp(str
, "No_qSuf") == 0)
1214 if (!modifiers
[OpcodeSpace
].value
)
1215 modifiers
[OpcodeSpace
].value
= space
;
1216 else if (modifiers
[OpcodeSpace
].value
!= space
)
1217 fail (_("%s:%d: Conflicting opcode space specifications\n"),
1221 _("%s:%d: Warning: redundant opcode space specification\n"),
1227 if (!modifiers
[OpcodePrefix
].value
)
1228 modifiers
[OpcodePrefix
].value
= prefix
;
1229 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1230 fail (_("%s:%d: Conflicting prefix specifications\n"),
1234 _("%s:%d: Warning: redundant prefix specification\n"),
1238 if (have_w
&& !bwlq_suf
)
1239 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1240 if (have_w
&& !(bwlq_suf
& 1))
1241 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1243 if (have_w
&& !(bwlq_suf
& ~1))
1245 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1248 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1258 output_operand_type (FILE *table
, enum operand_class
class,
1259 enum operand_instance instance
,
1260 const bitfield
*types
, unsigned int size
,
1261 enum stage stage
, const char *indent
)
1265 fprintf (table
, "{ { %d, %d, ", class, instance
);
1267 for (i
= 0; i
< size
- 1; i
++)
1269 if (((i
+ 3) % 20) != 0)
1270 fprintf (table
, "%d, ", types
[i
].value
);
1272 fprintf (table
, "%d,", types
[i
].value
);
1273 if (((i
+ 3) % 20) == 0)
1275 /* We need \\ for macro. */
1276 if (stage
== stage_macros
)
1277 fprintf (table
, " \\\n%s", indent
);
1279 fprintf (table
, "\n%s", indent
);
1283 fprintf (table
, "%d } }", types
[i
].value
);
1287 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1288 const char *indent
, int lineno
)
1290 char *str
, *next
, *last
;
1291 enum operand_class
class = ClassNone
;
1292 enum operand_instance instance
= InstanceNone
;
1293 bitfield types
[ARRAY_SIZE (operand_types
)];
1295 /* Copy the default operand type. */
1296 memcpy (types
, operand_types
, sizeof (types
));
1298 if (strcmp (op
, "0"))
1302 last
= op
+ strlen (op
);
1303 for (next
= op
; next
&& next
< last
; )
1305 str
= next_field (next
, '|', &next
, last
);
1310 if (!strncmp(str
, "Class=", 6))
1312 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1313 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1315 class = operand_classes
[i
].value
;
1321 if (str
&& !strncmp(str
, "Instance=", 9))
1323 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1324 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1326 instance
= operand_instances
[i
].value
;
1334 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1335 if (strcasecmp(str
, "BaseIndex") == 0)
1340 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1342 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1343 if (!active_cpu_flags
.bitfield
.cpu64
1344 && !active_cpu_flags
.bitfield
.cpumpx
)
1345 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1346 if (!active_cpu_flags
.bitfield
.cpu64
)
1347 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1348 if (!active_cpu_flags
.bitfield
.cpuno64
)
1349 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1352 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1357 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1358 char *last
, int lineno
)
1360 unsigned int i
, length
, prefix
= 0, space
= 0;
1361 char *base_opcode
, *extension_opcode
, *end
;
1362 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1363 unsigned long long opcode
;
1365 /* Find base_opcode. */
1366 base_opcode
= next_field (str
, ',', &str
, last
);
1368 /* Find extension_opcode. */
1369 extension_opcode
= next_field (str
, ',', &str
, last
);
1371 /* Find cpu_flags. */
1372 cpu_flags
= next_field (str
, ',', &str
, last
);
1374 /* Find opcode_modifier. */
1375 opcode_modifier
= next_field (str
, ',', &str
, last
);
1377 /* Remove the first {. */
1378 str
= remove_leading_whitespaces (str
);
1381 str
= remove_leading_whitespaces (str
+ 1);
1382 remove_trailing_whitespaces (str
);
1384 /* Remove } and trailing white space. */
1386 if (!i
|| str
[i
- 1] != '}')
1389 remove_trailing_whitespaces (str
);
1392 operand_types
[i
= 0] = NULL
;
1395 last
= str
+ strlen (str
);
1397 /* Find operand_types. */
1398 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1402 operand_types
[i
] = NULL
;
1406 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1410 opcode
= strtoull (base_opcode
, &end
, 0);
1412 /* Determine opcode length. */
1413 for (length
= 1; length
< 8; ++length
)
1414 if (!(opcode
>> (8 * length
)))
1417 /* Transform prefixes encoded in the opcode into opcode modifier
1421 switch (opcode
>> (8 * length
- 8))
1423 case 0x66: prefix
= PREFIX_0X66
; break;
1424 case 0xF3: prefix
= PREFIX_0XF3
; break;
1425 case 0xF2: prefix
= PREFIX_0XF2
; break;
1429 opcode
&= (1ULL << (8 * --length
)) - 1;
1432 /* Transform opcode space encoded in the opcode into opcode modifier
1434 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1436 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1438 default: space
= SPACE_0F
; break;
1439 case 0x38: space
= SPACE_0F38
; break;
1440 case 0x3A: space
= SPACE_0F3A
; break;
1443 if (space
!= SPACE_0F
&& --length
== 1)
1444 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1445 filename
, lineno
, name
);
1446 opcode
&= (1ULL << (8 * --length
)) - 1;
1450 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1451 filename
, lineno
, name
, 2 * length
, opcode
);
1453 fprintf (table
, " { \"%s\", 0x%0*llx%s, %s, %lu,\n",
1454 name
, 2 * (int)length
, opcode
, end
, extension_opcode
, i
);
1456 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1457 operand_types
, lineno
);
1459 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1461 fprintf (table
, " { ");
1463 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1465 if (!operand_types
[i
])
1468 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1474 fprintf (table
, ",\n ");
1476 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1479 fprintf (table
, " } },\n");
1482 struct opcode_hash_entry
1484 struct opcode_hash_entry
*next
;
1490 /* Calculate the hash value of an opcode hash entry P. */
1493 opcode_hash_hash (const void *p
)
1495 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1496 return htab_hash_string (entry
->name
);
1499 /* Compare a string Q against an opcode hash entry P. */
1502 opcode_hash_eq (const void *p
, const void *q
)
1504 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1505 const char *name
= (const char *) q
;
1506 return strcmp (name
, entry
->name
) == 0;
1510 parse_template (char *buf
, int lineno
)
1512 char sep
, *end
, *name
;
1513 struct template *tmpl
= xmalloc (sizeof (*tmpl
));
1514 struct template_instance
*last_inst
= NULL
;
1516 buf
= remove_leading_whitespaces (buf
+ 1);
1517 end
= strchr (buf
, ':');
1519 fail ("%s: %d: missing ':'\n", filename
, lineno
);
1521 remove_trailing_whitespaces (buf
);
1524 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1525 tmpl
->name
= xstrdup (buf
);
1527 tmpl
->params
= NULL
;
1529 struct template_param
*param
;
1531 buf
= remove_leading_whitespaces (end
);
1532 end
= strpbrk (buf
, ":,");
1534 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1538 remove_trailing_whitespaces (buf
);
1540 param
= xmalloc (sizeof (*param
));
1541 param
->name
= xstrdup (buf
);
1542 param
->next
= tmpl
->params
;
1543 tmpl
->params
= param
;
1544 } while (sep
== ':');
1546 tmpl
->instances
= NULL
;
1548 struct template_instance
*inst
;
1550 const struct template_param
*param
;
1552 buf
= remove_leading_whitespaces (end
);
1553 end
= strpbrk (buf
, ",>");
1555 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1560 inst
= xmalloc (sizeof (*inst
));
1564 cur
= next_field (buf
, ':', &next
, end
);
1565 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1567 for (param
= tmpl
->params
; param
; param
= param
->next
)
1569 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1571 cur
= next_field (next
, ':', &next
, end
);
1573 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1574 arg
->val
= xstrdup (cur
);
1575 arg
->next
= inst
->args
;
1579 if (tmpl
->instances
)
1580 last_inst
->next
= inst
;
1582 tmpl
->instances
= inst
;
1584 } while (sep
== ',');
1586 buf
= remove_leading_whitespaces (end
);
1588 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1589 filename
, lineno
, buf
);
1591 tmpl
->next
= templates
;
1596 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1597 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1599 static unsigned int idx
, opcode_array_size
;
1600 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1601 struct opcode_hash_entry
**hash_slot
, **entry
;
1602 char *ptr1
= strchr(name
, '<'), *ptr2
;
1606 /* Get the slot in hash table. */
1607 hash_slot
= (struct opcode_hash_entry
**)
1608 htab_find_slot_with_hash (opcode_hash_table
, name
,
1609 htab_hash_string (name
),
1612 if (*hash_slot
== NULL
)
1614 /* It is the new one. Put it on opcode array. */
1615 if (idx
>= opcode_array_size
)
1617 /* Grow the opcode array when needed. */
1618 opcode_array_size
+= 1024;
1619 opcode_array
= (struct opcode_hash_entry
**)
1620 xrealloc (opcode_array
,
1621 sizeof (*opcode_array
) * opcode_array_size
);
1622 *opcode_array_p
= opcode_array
;
1625 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1626 xmalloc (sizeof (struct opcode_hash_entry
));
1627 opcode_array
[idx
]->next
= NULL
;
1628 opcode_array
[idx
]->name
= xstrdup (name
);
1629 opcode_array
[idx
]->opcode
= xstrdup (str
);
1630 opcode_array
[idx
]->lineno
= lineno
;
1631 *hash_slot
= opcode_array
[idx
];
1636 /* Append it to the existing one. */
1638 while ((*entry
) != NULL
)
1639 entry
= &(*entry
)->next
;
1640 *entry
= (struct opcode_hash_entry
*)
1641 xmalloc (sizeof (struct opcode_hash_entry
));
1642 (*entry
)->next
= NULL
;
1643 (*entry
)->name
= (*hash_slot
)->name
;
1644 (*entry
)->opcode
= xstrdup (str
);
1645 (*entry
)->lineno
= lineno
;
1648 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1649 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1652 const struct template *tmpl
;
1653 const struct template_instance
*inst
;
1656 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1657 remove_trailing_whitespaces (ptr1
);
1661 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1662 if (!strcmp(ptr1
, tmpl
->name
))
1665 fail ("reference to unknown template '%s'\n", ptr1
);
1667 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1669 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1670 char *str2
= xmalloc(2 * strlen(str
));
1673 strcpy (name2
, name
);
1674 strcat (name2
, inst
->name
);
1675 strcat (name2
, ptr2
);
1677 for (ptr1
= str2
, src
= str
; *src
; )
1679 const char *ident
= tmpl
->name
, *end
;
1680 const struct template_param
*param
;
1681 const struct template_arg
*arg
;
1683 if ((*ptr1
= *src
++) != '<')
1688 while (ISSPACE(*src
))
1690 while (*ident
&& *src
== *ident
)
1692 while (ISSPACE(*src
))
1694 if (*src
!= ':' || *ident
!= '\0')
1696 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1697 ptr1
+= ident
- tmpl
->name
;
1700 while (ISSPACE(*++src
))
1704 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1707 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1708 param
= param
->next
, arg
= arg
->next
)
1710 if (end
- src
== strlen (param
->name
)
1711 && !memcmp (src
, param
->name
, end
- src
))
1719 fail ("template '%s' has no parameter '%.*s'\n",
1720 tmpl
->name
, (int)(end
- src
), src
);
1722 while (ISSPACE(*src
))
1725 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1727 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1728 ptr1
+= strlen(arg
->val
);
1734 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1746 process_i386_opcodes (FILE *table
)
1751 char *str
, *p
, *last
, *name
;
1752 htab_t opcode_hash_table
;
1753 struct opcode_hash_entry
**opcode_array
= NULL
;
1754 int lineno
= 0, marker
= 0;
1756 filename
= "i386-opc.tbl";
1760 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1761 opcode_hash_eq
, NULL
,
1764 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1765 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1767 /* Put everything on opcode array. */
1770 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1775 p
= remove_leading_whitespaces (buf
);
1777 /* Skip comments. */
1778 str
= strstr (p
, "//");
1782 /* Remove trailing white spaces. */
1783 remove_trailing_whitespaces (p
);
1788 if (!strcmp("### MARKER ###", buf
))
1792 /* Since we ignore all included files (we only care about their
1793 #define-s here), we don't need to monitor filenames. The final
1794 line number directive is going to refer to the main source file
1799 p
= remove_leading_whitespaces (p
+ 1);
1800 if (!strncmp(p
, "line", 4))
1802 ln
= strtoul (p
, &end
, 10);
1803 if (ln
> 1 && ln
< INT_MAX
1804 && *remove_leading_whitespaces (end
) == '"')
1807 /* Ignore comments. */
1812 parse_template (p
, lineno
);
1820 last
= p
+ strlen (p
);
1823 name
= next_field (p
, ',', &str
, last
);
1825 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1829 /* Process opcode array. */
1830 for (j
= 0; j
< i
; j
++)
1832 struct opcode_hash_entry
*next
;
1834 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1838 lineno
= next
->lineno
;
1839 last
= str
+ strlen (str
);
1840 output_i386_opcode (table
, name
, str
, last
, lineno
);
1846 fprintf (table
, " { NULL, 0, 0, 0,\n");
1848 process_i386_opcode_modifier (table
, "0", 0, 0, NULL
, -1);
1850 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1852 fprintf (table
, " { ");
1853 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1854 fprintf (table
, " } }\n");
1856 fprintf (table
, "};\n");
1860 process_i386_registers (FILE *table
)
1864 char *str
, *p
, *last
;
1865 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1866 char *dw2_32_num
, *dw2_64_num
;
1869 filename
= "i386-reg.tbl";
1870 fp
= fopen (filename
, "r");
1872 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1875 fprintf (table
, "\n/* i386 register table. */\n\n");
1876 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1880 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1885 p
= remove_leading_whitespaces (buf
);
1887 /* Skip comments. */
1888 str
= strstr (p
, "//");
1892 /* Remove trailing white spaces. */
1893 remove_trailing_whitespaces (p
);
1898 fprintf (table
, "%s\n", p
);
1906 last
= p
+ strlen (p
);
1908 /* Find reg_name. */
1909 reg_name
= next_field (p
, ',', &str
, last
);
1911 /* Find reg_type. */
1912 reg_type
= next_field (str
, ',', &str
, last
);
1914 /* Find reg_flags. */
1915 reg_flags
= next_field (str
, ',', &str
, last
);
1918 reg_num
= next_field (str
, ',', &str
, last
);
1920 fprintf (table
, " { \"%s\",\n ", reg_name
);
1922 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1925 /* Find 32-bit Dwarf2 register number. */
1926 dw2_32_num
= next_field (str
, ',', &str
, last
);
1928 /* Find 64-bit Dwarf2 register number. */
1929 dw2_64_num
= next_field (str
, ',', &str
, last
);
1931 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1932 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1937 fprintf (table
, "};\n");
1939 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1943 process_i386_initializers (void)
1946 FILE *fp
= fopen ("i386-init.h", "w");
1950 fail (_("can't create i386-init.h, errno = %s\n"),
1953 process_copyright (fp
);
1955 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1957 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1958 init
= xstrdup (cpu_flag_init
[i
].init
);
1959 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1963 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1965 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1966 init
= xstrdup (operand_type_init
[i
].init
);
1967 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1975 /* Program options. */
1976 #define OPTION_SRCDIR 200
1978 struct option long_options
[] =
1980 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1981 {"debug", no_argument
, NULL
, 'd'},
1982 {"version", no_argument
, NULL
, 'V'},
1983 {"help", no_argument
, NULL
, 'h'},
1984 {0, no_argument
, NULL
, 0}
1988 print_version (void)
1990 printf ("%s: version 1.0\n", program_name
);
1995 usage (FILE * stream
, int status
)
1997 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2003 main (int argc
, char **argv
)
2005 extern int chdir (char *);
2006 char *srcdir
= NULL
;
2008 unsigned int i
, cpumax
;
2011 program_name
= *argv
;
2012 xmalloc_set_program_name (program_name
);
2014 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2039 if (chdir (srcdir
) != 0)
2040 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2041 srcdir
, xstrerror (errno
));
2043 /* cpu_flags isn't sorted by position. */
2045 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2046 if (cpu_flags
[i
].position
> cpumax
)
2047 cpumax
= cpu_flags
[i
].position
;
2049 /* Check the unused bitfield in i386_cpu_flags. */
2051 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2053 if ((cpumax
- 1) != CpuMax
)
2054 fail (_("CpuMax != %d!\n"), cpumax
);
2056 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2058 if (cpumax
!= CpuMax
)
2059 fail (_("CpuMax != %d!\n"), cpumax
);
2061 c
= CpuNumOfBits
- CpuMax
- 1;
2063 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2066 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2068 /* Check the unused bitfield in i386_operand_type. */
2070 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2073 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2076 c
= OTNumOfBits
- OTNum
;
2078 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2081 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2084 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2085 sizeof (opcode_modifiers
[0]), compare
);
2087 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2088 sizeof (operand_types
[0]), compare
);
2090 table
= fopen ("i386-tbl.h", "w");
2092 fail (_("can't create i386-tbl.h, errno = %s\n"),
2095 process_copyright (table
);
2097 process_i386_opcodes (table
);
2098 process_i386_registers (table
);
2099 process_i386_initializers ();