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_DISP64",
480 { "OPERAND_TYPE_INOUTPORTREG",
481 "Instance=RegD|Word" },
482 { "OPERAND_TYPE_SHIFTCOUNT",
483 "Instance=RegC|Byte" },
484 { "OPERAND_TYPE_CONTROL",
486 { "OPERAND_TYPE_TEST",
488 { "OPERAND_TYPE_DEBUG",
490 { "OPERAND_TYPE_FLOATREG",
492 { "OPERAND_TYPE_FLOATACC",
493 "Instance=Accum|Tbyte" },
494 { "OPERAND_TYPE_SREG",
496 { "OPERAND_TYPE_REGMMX",
498 { "OPERAND_TYPE_REGXMM",
499 "Class=RegSIMD|Xmmword" },
500 { "OPERAND_TYPE_REGYMM",
501 "Class=RegSIMD|Ymmword" },
502 { "OPERAND_TYPE_REGZMM",
503 "Class=RegSIMD|Zmmword" },
504 { "OPERAND_TYPE_REGTMM",
505 "Class=RegSIMD|Tmmword" },
506 { "OPERAND_TYPE_REGMASK",
508 { "OPERAND_TYPE_REGBND",
510 { "OPERAND_TYPE_ACC8",
511 "Instance=Accum|Byte" },
512 { "OPERAND_TYPE_ACC16",
513 "Instance=Accum|Word" },
514 { "OPERAND_TYPE_ACC32",
515 "Instance=Accum|Dword" },
516 { "OPERAND_TYPE_ACC64",
517 "Instance=Accum|Qword" },
518 { "OPERAND_TYPE_DISP16_32",
520 { "OPERAND_TYPE_ANYDISP",
521 "Disp8|Disp16|Disp32|Disp64" },
522 { "OPERAND_TYPE_IMM16_32",
524 { "OPERAND_TYPE_IMM16_32S",
526 { "OPERAND_TYPE_IMM16_32_32S",
527 "Imm16|Imm32|Imm32S" },
528 { "OPERAND_TYPE_IMM32_64",
530 { "OPERAND_TYPE_IMM32_32S_DISP32",
531 "Imm32|Imm32S|Disp32" },
532 { "OPERAND_TYPE_IMM64_DISP64",
534 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
535 "Imm32|Imm32S|Imm64|Disp32" },
536 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
537 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
538 { "OPERAND_TYPE_ANYIMM",
539 "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
542 typedef struct bitfield
549 #define BITFIELD(n) { n, 0, #n }
551 static bitfield cpu_flags
[] =
561 BITFIELD (CpuClflush
),
563 BITFIELD (CpuSYSCALL
),
568 BITFIELD (CpuFISTTP
),
574 BITFIELD (CpuSSE4_1
),
575 BITFIELD (CpuSSE4_2
),
578 BITFIELD (CpuAVX512F
),
579 BITFIELD (CpuAVX512CD
),
580 BITFIELD (CpuAVX512ER
),
581 BITFIELD (CpuAVX512PF
),
582 BITFIELD (CpuAVX512VL
),
583 BITFIELD (CpuAVX512DQ
),
584 BITFIELD (CpuAVX512BW
),
588 BITFIELD (Cpu3dnowA
),
589 BITFIELD (CpuPadLock
),
594 BITFIELD (CpuXsaveopt
),
596 BITFIELD (CpuPCLMUL
),
607 BITFIELD (CpuRdtscp
),
608 BITFIELD (CpuFSGSBase
),
613 BITFIELD (CpuPOPCNT
),
616 BITFIELD (CpuINVPCID
),
617 BITFIELD (CpuVMFUNC
),
618 BITFIELD (CpuRDSEED
),
620 BITFIELD (CpuPRFCHW
),
623 BITFIELD (CpuClflushOpt
),
624 BITFIELD (CpuXSAVES
),
625 BITFIELD (CpuXSAVEC
),
626 BITFIELD (CpuPREFETCHWT1
),
630 BITFIELD (CpuAVX512IFMA
),
631 BITFIELD (CpuAVX512VBMI
),
632 BITFIELD (CpuAVX512_4FMAPS
),
633 BITFIELD (CpuAVX512_4VNNIW
),
634 BITFIELD (CpuAVX512_VPOPCNTDQ
),
635 BITFIELD (CpuAVX512_VBMI2
),
636 BITFIELD (CpuAVX512_VNNI
),
637 BITFIELD (CpuAVX512_BITALG
),
638 BITFIELD (CpuAVX512_BF16
),
639 BITFIELD (CpuAVX512_VP2INTERSECT
),
641 BITFIELD (CpuAVX_VNNI
),
642 BITFIELD (CpuAVX512_FP16
),
643 BITFIELD (CpuMWAITX
),
644 BITFIELD (CpuCLZERO
),
647 BITFIELD (CpuPTWRITE
),
652 BITFIELD (CpuVPCLMULQDQ
),
653 BITFIELD (CpuWBNOINVD
),
654 BITFIELD (CpuPCONFIG
),
655 BITFIELD (CpuWAITPKG
),
657 BITFIELD (CpuCLDEMOTE
),
658 BITFIELD (CpuAMX_INT8
),
659 BITFIELD (CpuAMX_BF16
),
660 BITFIELD (CpuAMX_TILE
),
661 BITFIELD (CpuMOVDIRI
),
662 BITFIELD (CpuMOVDIR64B
),
663 BITFIELD (CpuENQCMD
),
664 BITFIELD (CpuSERIALIZE
),
666 BITFIELD (CpuMCOMMIT
),
667 BITFIELD (CpuSEV_ES
),
668 BITFIELD (CpuTSXLDTRK
),
670 BITFIELD (CpuWideKL
),
671 BITFIELD (CpuHRESET
),
672 BITFIELD (CpuINVLPGB
),
673 BITFIELD (CpuTLBSYNC
),
678 BITFIELD (CpuUnused
),
682 static bitfield opcode_modifiers
[] =
692 BITFIELD (CheckRegSize
),
693 BITFIELD (DistinctDest
),
694 BITFIELD (MnemonicSize
),
705 BITFIELD (BNDPrefixOk
),
706 BITFIELD (RegKludge
),
707 BITFIELD (Implicit1stXmm0
),
711 BITFIELD (AddrPrefixOpReg
),
716 BITFIELD (PseudoVexPrefix
),
720 BITFIELD (OpcodeSpace
),
721 BITFIELD (OpcodePrefix
),
722 BITFIELD (VexSources
),
727 BITFIELD (Broadcast
),
728 BITFIELD (StaticRounding
),
730 BITFIELD (Disp8MemShift
),
731 BITFIELD (NoDefMask
),
732 BITFIELD (ImplicitQuadGroup
),
733 BITFIELD (SwapSources
),
735 BITFIELD (ATTMnemonic
),
736 BITFIELD (ATTSyntax
),
737 BITFIELD (IntelSyntax
),
741 #define CLASS(n) #n, n
743 static const struct {
745 enum operand_class value
;
746 } operand_classes
[] = {
760 #define INSTANCE(n) #n, n
762 static const struct {
764 enum operand_instance value
;
765 } operand_instances
[] = {
774 static bitfield operand_types
[] =
783 BITFIELD (BaseIndex
),
798 BITFIELD (Unspecified
),
804 static const char *filename
;
805 static i386_cpu_flags active_cpu_flags
;
806 static int active_isstring
;
808 struct template_arg
{
809 const struct template_arg
*next
;
813 struct template_instance
{
814 const struct template_instance
*next
;
816 const struct template_arg
*args
;
819 struct template_param
{
820 const struct template_param
*next
;
825 struct template *next
;
827 const struct template_instance
*instances
;
828 const struct template_param
*params
;
831 static struct template *templates
;
834 compare (const void *x
, const void *y
)
836 const bitfield
*xp
= (const bitfield
*) x
;
837 const bitfield
*yp
= (const bitfield
*) y
;
838 return xp
->position
- yp
->position
;
842 fail (const char *message
, ...)
846 va_start (args
, message
);
847 fprintf (stderr
, _("%s: error: "), program_name
);
848 vfprintf (stderr
, message
, args
);
854 process_copyright (FILE *fp
)
856 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
857 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
859 This file is part of the GNU opcodes library.\n\
861 This library is free software; you can redistribute it and/or modify\n\
862 it under the terms of the GNU General Public License as published by\n\
863 the Free Software Foundation; either version 3, or (at your option)\n\
864 any later version.\n\
866 It is distributed in the hope that it will be useful, but WITHOUT\n\
867 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
868 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
869 License for more details.\n\
871 You should have received a copy of the GNU General Public License\n\
872 along with this program; if not, write to the Free Software\n\
873 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
874 MA 02110-1301, USA. */\n");
877 /* Remove leading white spaces. */
880 remove_leading_whitespaces (char *str
)
882 while (ISSPACE (*str
))
887 /* Remove trailing white spaces. */
890 remove_trailing_whitespaces (char *str
)
892 size_t last
= strlen (str
);
900 if (ISSPACE (str
[last
]))
908 /* Find next field separated by SEP and terminate it. Return a
909 pointer to the one after it. */
912 next_field (char *str
, char sep
, char **next
, char *last
)
916 p
= remove_leading_whitespaces (str
);
917 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
920 remove_trailing_whitespaces (p
);
930 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
933 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
936 char *str
, *next
, *last
;
939 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
940 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
942 /* Turn on selective bits. */
943 char *init
= xstrdup (cpu_flag_init
[i
].init
);
944 last
= init
+ strlen (init
);
945 for (next
= init
; next
&& next
< last
; )
947 str
= next_field (next
, '|', &next
, last
);
949 set_bitfield (str
, array
, 1, size
, lineno
);
959 set_bitfield (char *f
, bitfield
*array
, int value
,
960 unsigned int size
, int lineno
)
964 /* Ignore empty fields; they may result from template expansions. */
968 for (i
= 0; i
< size
; i
++)
969 if (strcasecmp (array
[i
].name
, f
) == 0)
971 array
[i
].value
= value
;
977 const char *v
= strchr (f
, '=');
984 for (i
= 0; i
< size
; i
++)
985 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
987 value
= strtol (v
+ 1, &end
, 0);
990 array
[i
].value
= value
;
998 /* Handle CPU_XXX_FLAGS. */
999 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
1003 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
1005 fail (_("unknown bitfield: %s\n"), f
);
1009 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
1010 int macro
, const char *comma
, const char *indent
)
1014 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
1016 fprintf (table
, "%s{ { ", indent
);
1018 for (i
= 0; i
< size
- 1; i
++)
1020 if (((i
+ 1) % 20) != 0)
1021 fprintf (table
, "%d, ", flags
[i
].value
);
1023 fprintf (table
, "%d,", flags
[i
].value
);
1024 if (((i
+ 1) % 20) == 0)
1026 /* We need \\ for macro. */
1028 fprintf (table
, " \\\n %s", indent
);
1030 fprintf (table
, "\n %s", indent
);
1033 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
1036 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
1040 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
1041 const char *comma
, const char *indent
,
1044 char *str
, *next
= flag
, *last
;
1047 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
1049 /* Copy the default cpu flags. */
1050 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
1054 last
= flag
+ strlen (flag
);
1061 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
1068 /* First we turn on everything except for cpu64, cpuno64, and - if
1069 present - the padding field. */
1070 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1071 if (flags
[i
].position
< Cpu64
)
1074 /* Turn off selective bits. */
1078 if (strcmp (flag
, "0"))
1080 /* Turn on/off selective bits. */
1081 last
= flag
+ strlen (flag
);
1082 for (; next
&& next
< last
; )
1084 str
= next_field (next
, '|', &next
, last
);
1086 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
1090 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1095 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1099 fprintf (table
, " { ");
1101 for (i
= 0; i
< size
- 1; i
++)
1103 if (((i
+ 1) % 20) != 0)
1104 fprintf (table
, "%d, ", modifier
[i
].value
);
1106 fprintf (table
, "%d,", modifier
[i
].value
);
1107 if (((i
+ 1) % 20) == 0)
1108 fprintf (table
, "\n ");
1111 fprintf (table
, "%d },\n", modifier
[i
].value
);
1114 /* Returns LOG2 of element size. */
1116 get_element_size (char **opnd
, int lineno
)
1118 char *str
, *next
, *last
, *op
;
1119 const char *full
= opnd
[0];
1120 int elem_size
= INT_MAX
;
1122 /* Find the memory operand. */
1123 while (full
!= NULL
&& strstr(full
, "BaseIndex") == NULL
)
1126 fail (_("%s: %d: no memory operand\n"), filename
, lineno
);
1128 op
= xstrdup (full
);
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 smallest element size, no need to check
1142 else if (strcasecmp(str
, "Word") == 0)
1147 else if (strcasecmp(str
, "Dword") == 0)
1152 else if (strcasecmp(str
, "Qword") == 0)
1161 if (elem_size
== INT_MAX
)
1162 fail (_("%s: %d: unknown element size: %s\n"), filename
, lineno
, full
);
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
= get_element_size (opnd
, lineno
) + BYTE_BROADCAST
;
1192 else if (strcasecmp(str
, "Disp8MemShift") == 0)
1193 val
= get_element_size (opnd
, lineno
);
1195 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1197 if (strcasecmp(str
, "IsString") == 0)
1198 active_isstring
= 1;
1200 if (strcasecmp(str
, "W") == 0)
1203 if (strcasecmp(str
, "No_bSuf") == 0)
1205 if (strcasecmp(str
, "No_wSuf") == 0)
1207 if (strcasecmp(str
, "No_lSuf") == 0)
1209 if (strcasecmp(str
, "No_qSuf") == 0)
1216 if (!modifiers
[OpcodeSpace
].value
)
1217 modifiers
[OpcodeSpace
].value
= space
;
1218 else if (modifiers
[OpcodeSpace
].value
!= space
)
1219 fail (_("%s:%d: Conflicting opcode space specifications\n"),
1223 _("%s:%d: Warning: redundant opcode space specification\n"),
1229 if (!modifiers
[OpcodePrefix
].value
)
1230 modifiers
[OpcodePrefix
].value
= prefix
;
1231 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1232 fail (_("%s:%d: Conflicting prefix specifications\n"),
1236 _("%s:%d: Warning: redundant prefix specification\n"),
1240 if (have_w
&& !bwlq_suf
)
1241 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1242 if (have_w
&& !(bwlq_suf
& 1))
1243 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1245 if (have_w
&& !(bwlq_suf
& ~1))
1247 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1250 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1260 output_operand_type (FILE *table
, enum operand_class
class,
1261 enum operand_instance instance
,
1262 const bitfield
*types
, unsigned int size
,
1263 enum stage stage
, const char *indent
)
1267 fprintf (table
, "{ { %d, %d, ", class, instance
);
1269 for (i
= 0; i
< size
- 1; i
++)
1271 if (((i
+ 3) % 20) != 0)
1272 fprintf (table
, "%d, ", types
[i
].value
);
1274 fprintf (table
, "%d,", types
[i
].value
);
1275 if (((i
+ 3) % 20) == 0)
1277 /* We need \\ for macro. */
1278 if (stage
== stage_macros
)
1279 fprintf (table
, " \\\n%s", indent
);
1281 fprintf (table
, "\n%s", indent
);
1285 fprintf (table
, "%d } }", types
[i
].value
);
1289 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1290 const char *indent
, int lineno
)
1292 char *str
, *next
, *last
;
1293 enum operand_class
class = ClassNone
;
1294 enum operand_instance instance
= InstanceNone
;
1295 bitfield types
[ARRAY_SIZE (operand_types
)];
1297 /* Copy the default operand type. */
1298 memcpy (types
, operand_types
, sizeof (types
));
1300 if (strcmp (op
, "0"))
1304 last
= op
+ strlen (op
);
1305 for (next
= op
; next
&& next
< last
; )
1307 str
= next_field (next
, '|', &next
, last
);
1312 if (!strncmp(str
, "Class=", 6))
1314 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1315 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1317 class = operand_classes
[i
].value
;
1323 if (str
&& !strncmp(str
, "Instance=", 9))
1325 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1326 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1328 instance
= operand_instances
[i
].value
;
1336 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1337 if (strcasecmp(str
, "BaseIndex") == 0)
1342 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1344 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1345 if (!active_cpu_flags
.bitfield
.cpu64
1346 && !active_cpu_flags
.bitfield
.cpumpx
)
1347 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1348 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1351 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1356 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1357 char *last
, int lineno
)
1359 unsigned int i
, length
, prefix
= 0, space
= 0;
1360 char *base_opcode
, *extension_opcode
, *end
;
1361 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1362 unsigned long long opcode
;
1364 /* Find base_opcode. */
1365 base_opcode
= next_field (str
, ',', &str
, last
);
1367 /* Find extension_opcode. */
1368 extension_opcode
= next_field (str
, ',', &str
, last
);
1370 /* Find cpu_flags. */
1371 cpu_flags
= next_field (str
, ',', &str
, last
);
1373 /* Find opcode_modifier. */
1374 opcode_modifier
= next_field (str
, ',', &str
, last
);
1376 /* Remove the first {. */
1377 str
= remove_leading_whitespaces (str
);
1380 str
= remove_leading_whitespaces (str
+ 1);
1381 remove_trailing_whitespaces (str
);
1383 /* Remove } and trailing white space. */
1385 if (!i
|| str
[i
- 1] != '}')
1388 remove_trailing_whitespaces (str
);
1391 operand_types
[i
= 0] = NULL
;
1394 last
= str
+ strlen (str
);
1396 /* Find operand_types. */
1397 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1401 operand_types
[i
] = NULL
;
1405 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1409 opcode
= strtoull (base_opcode
, &end
, 0);
1411 /* Determine opcode length. */
1412 for (length
= 1; length
< 8; ++length
)
1413 if (!(opcode
>> (8 * length
)))
1416 /* Transform prefixes encoded in the opcode into opcode modifier
1420 switch (opcode
>> (8 * length
- 8))
1422 case 0x66: prefix
= PREFIX_0X66
; break;
1423 case 0xF3: prefix
= PREFIX_0XF3
; break;
1424 case 0xF2: prefix
= PREFIX_0XF2
; break;
1428 opcode
&= (1ULL << (8 * --length
)) - 1;
1431 /* Transform opcode space encoded in the opcode into opcode modifier
1433 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1435 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1437 default: space
= SPACE_0F
; break;
1438 case 0x38: space
= SPACE_0F38
; break;
1439 case 0x3A: space
= SPACE_0F3A
; break;
1442 if (space
!= SPACE_0F
&& --length
== 1)
1443 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1444 filename
, lineno
, name
);
1445 opcode
&= (1ULL << (8 * --length
)) - 1;
1449 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1450 filename
, lineno
, name
, 2 * length
, opcode
);
1452 fprintf (table
, " { \"%s\", 0x%0*llx%s, %lu, %s,\n",
1453 name
, 2 * (int)length
, opcode
, end
, i
, extension_opcode
);
1455 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1456 operand_types
, lineno
);
1458 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1460 fprintf (table
, " { ");
1462 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1464 if (!operand_types
[i
])
1467 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1473 fprintf (table
, ",\n ");
1475 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1478 fprintf (table
, " } },\n");
1481 struct opcode_hash_entry
1483 struct opcode_hash_entry
*next
;
1489 /* Calculate the hash value of an opcode hash entry P. */
1492 opcode_hash_hash (const void *p
)
1494 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1495 return htab_hash_string (entry
->name
);
1498 /* Compare a string Q against an opcode hash entry P. */
1501 opcode_hash_eq (const void *p
, const void *q
)
1503 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1504 const char *name
= (const char *) q
;
1505 return strcmp (name
, entry
->name
) == 0;
1509 parse_template (char *buf
, int lineno
)
1511 char sep
, *end
, *name
;
1512 struct template *tmpl
;
1513 struct template_instance
*last_inst
= NULL
;
1515 buf
= remove_leading_whitespaces (buf
+ 1);
1516 end
= strchr (buf
, ':');
1519 struct template *prev
= NULL
;
1521 end
= strchr (buf
, '>');
1523 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1524 if (*remove_leading_whitespaces (end
+ 1))
1525 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1527 remove_trailing_whitespaces (buf
);
1528 /* Don't bother freeing the various structures. */
1529 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1530 if (!strcmp (buf
, tmpl
->name
))
1533 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1535 prev
->next
= tmpl
->next
;
1537 templates
= tmpl
->next
;
1541 remove_trailing_whitespaces (buf
);
1544 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1545 tmpl
= xmalloc (sizeof (*tmpl
));
1546 tmpl
->name
= xstrdup (buf
);
1548 tmpl
->params
= NULL
;
1550 struct template_param
*param
;
1552 buf
= remove_leading_whitespaces (end
);
1553 end
= strpbrk (buf
, ":,");
1555 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1559 remove_trailing_whitespaces (buf
);
1561 param
= xmalloc (sizeof (*param
));
1562 param
->name
= xstrdup (buf
);
1563 param
->next
= tmpl
->params
;
1564 tmpl
->params
= param
;
1565 } while (sep
== ':');
1567 tmpl
->instances
= NULL
;
1569 struct template_instance
*inst
;
1571 const struct template_param
*param
;
1573 buf
= remove_leading_whitespaces (end
);
1574 end
= strpbrk (buf
, ",>");
1576 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1581 inst
= xmalloc (sizeof (*inst
));
1585 cur
= next_field (buf
, ':', &next
, end
);
1586 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1588 for (param
= tmpl
->params
; param
; param
= param
->next
)
1590 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1592 cur
= next_field (next
, ':', &next
, end
);
1594 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1595 arg
->val
= xstrdup (cur
);
1596 arg
->next
= inst
->args
;
1600 if (tmpl
->instances
)
1601 last_inst
->next
= inst
;
1603 tmpl
->instances
= inst
;
1605 } while (sep
== ',');
1607 buf
= remove_leading_whitespaces (end
);
1609 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1610 filename
, lineno
, buf
);
1612 tmpl
->next
= templates
;
1617 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1618 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1620 static unsigned int idx
, opcode_array_size
;
1621 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1622 struct opcode_hash_entry
**hash_slot
, **entry
;
1623 char *ptr1
= strchr(name
, '<'), *ptr2
;
1627 /* Get the slot in hash table. */
1628 hash_slot
= (struct opcode_hash_entry
**)
1629 htab_find_slot_with_hash (opcode_hash_table
, name
,
1630 htab_hash_string (name
),
1633 if (*hash_slot
== NULL
)
1635 /* It is the new one. Put it on opcode array. */
1636 if (idx
>= opcode_array_size
)
1638 /* Grow the opcode array when needed. */
1639 opcode_array_size
+= 1024;
1640 opcode_array
= (struct opcode_hash_entry
**)
1641 xrealloc (opcode_array
,
1642 sizeof (*opcode_array
) * opcode_array_size
);
1643 *opcode_array_p
= opcode_array
;
1646 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1647 xmalloc (sizeof (struct opcode_hash_entry
));
1648 opcode_array
[idx
]->next
= NULL
;
1649 opcode_array
[idx
]->name
= xstrdup (name
);
1650 opcode_array
[idx
]->opcode
= xstrdup (str
);
1651 opcode_array
[idx
]->lineno
= lineno
;
1652 *hash_slot
= opcode_array
[idx
];
1657 /* Append it to the existing one. */
1659 while ((*entry
) != NULL
)
1660 entry
= &(*entry
)->next
;
1661 *entry
= (struct opcode_hash_entry
*)
1662 xmalloc (sizeof (struct opcode_hash_entry
));
1663 (*entry
)->next
= NULL
;
1664 (*entry
)->name
= (*hash_slot
)->name
;
1665 (*entry
)->opcode
= xstrdup (str
);
1666 (*entry
)->lineno
= lineno
;
1669 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1670 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1673 const struct template *tmpl
;
1674 const struct template_instance
*inst
;
1677 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1678 remove_trailing_whitespaces (ptr1
);
1682 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1683 if (!strcmp(ptr1
, tmpl
->name
))
1686 fail ("reference to unknown template '%s'\n", ptr1
);
1688 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1690 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1691 char *str2
= xmalloc(2 * strlen(str
));
1694 strcpy (name2
, name
);
1695 strcat (name2
, inst
->name
);
1696 strcat (name2
, ptr2
);
1698 for (ptr1
= str2
, src
= str
; *src
; )
1700 const char *ident
= tmpl
->name
, *end
;
1701 const struct template_param
*param
;
1702 const struct template_arg
*arg
;
1704 if ((*ptr1
= *src
++) != '<')
1709 while (ISSPACE(*src
))
1711 while (*ident
&& *src
== *ident
)
1713 while (ISSPACE(*src
))
1715 if (*src
!= ':' || *ident
!= '\0')
1717 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1718 ptr1
+= ident
- tmpl
->name
;
1721 while (ISSPACE(*++src
))
1725 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1728 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1729 param
= param
->next
, arg
= arg
->next
)
1731 if (end
- src
== strlen (param
->name
)
1732 && !memcmp (src
, param
->name
, end
- src
))
1740 fail ("template '%s' has no parameter '%.*s'\n",
1741 tmpl
->name
, (int)(end
- src
), src
);
1743 while (ISSPACE(*src
))
1746 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1748 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1749 ptr1
+= strlen(arg
->val
);
1755 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1767 process_i386_opcodes (FILE *table
)
1772 char *str
, *p
, *last
, *name
;
1773 htab_t opcode_hash_table
;
1774 struct opcode_hash_entry
**opcode_array
= NULL
;
1775 int lineno
= 0, marker
= 0;
1777 filename
= "i386-opc.tbl";
1781 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1782 opcode_hash_eq
, NULL
,
1785 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1786 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1788 /* Put everything on opcode array. */
1791 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1794 p
= remove_leading_whitespaces (buf
);
1800 /* Skip comments. */
1801 str
= strstr (p
, "//");
1805 remove_trailing_whitespaces (p
);
1809 /* Look for line continuation character. */
1810 remove_trailing_whitespaces (p
);
1812 if (!j
|| buf
[j
- 1] != '+')
1814 if (j
>= sizeof (buf
) - 1)
1815 fail (_("%s: %d: (continued) line too long\n"), filename
, lineno
);
1817 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1819 fprintf (stderr
, "%s: Line continuation on last line?\n",
1828 if (!strcmp("### MARKER ###", buf
))
1832 /* Since we ignore all included files (we only care about their
1833 #define-s here), we don't need to monitor filenames. The final
1834 line number directive is going to refer to the main source file
1839 p
= remove_leading_whitespaces (p
+ 1);
1840 if (!strncmp(p
, "line", 4))
1842 ln
= strtoul (p
, &end
, 10);
1843 if (ln
> 1 && ln
< INT_MAX
1844 && *remove_leading_whitespaces (end
) == '"')
1847 /* Ignore comments. */
1852 parse_template (p
, lineno
);
1860 last
= p
+ strlen (p
);
1863 name
= next_field (p
, ',', &str
, last
);
1865 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1869 /* Process opcode array. */
1870 for (j
= 0; j
< i
; j
++)
1872 struct opcode_hash_entry
*next
;
1874 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1878 lineno
= next
->lineno
;
1879 last
= str
+ strlen (str
);
1880 output_i386_opcode (table
, name
, str
, last
, lineno
);
1886 fprintf (table
, " { NULL, 0, 0, 0,\n");
1888 process_i386_opcode_modifier (table
, "0", 0, 0, NULL
, -1);
1890 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1892 fprintf (table
, " { ");
1893 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1894 fprintf (table
, " } }\n");
1896 fprintf (table
, "};\n");
1900 process_i386_registers (FILE *table
)
1904 char *str
, *p
, *last
;
1905 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1906 char *dw2_32_num
, *dw2_64_num
;
1909 filename
= "i386-reg.tbl";
1910 fp
= fopen (filename
, "r");
1912 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1915 fprintf (table
, "\n/* i386 register table. */\n\n");
1916 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1920 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1925 p
= remove_leading_whitespaces (buf
);
1927 /* Skip comments. */
1928 str
= strstr (p
, "//");
1932 /* Remove trailing white spaces. */
1933 remove_trailing_whitespaces (p
);
1938 fprintf (table
, "%s\n", p
);
1946 last
= p
+ strlen (p
);
1948 /* Find reg_name. */
1949 reg_name
= next_field (p
, ',', &str
, last
);
1951 /* Find reg_type. */
1952 reg_type
= next_field (str
, ',', &str
, last
);
1954 /* Find reg_flags. */
1955 reg_flags
= next_field (str
, ',', &str
, last
);
1958 reg_num
= next_field (str
, ',', &str
, last
);
1960 fprintf (table
, " { \"%s\",\n ", reg_name
);
1962 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1965 /* Find 32-bit Dwarf2 register number. */
1966 dw2_32_num
= next_field (str
, ',', &str
, last
);
1968 /* Find 64-bit Dwarf2 register number. */
1969 dw2_64_num
= next_field (str
, ',', &str
, last
);
1971 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1972 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1977 fprintf (table
, "};\n");
1979 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1983 process_i386_initializers (void)
1986 FILE *fp
= fopen ("i386-init.h", "w");
1990 fail (_("can't create i386-init.h, errno = %s\n"),
1993 process_copyright (fp
);
1995 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1997 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1998 init
= xstrdup (cpu_flag_init
[i
].init
);
1999 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
2003 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
2005 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
2006 init
= xstrdup (operand_type_init
[i
].init
);
2007 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
2015 /* Program options. */
2016 #define OPTION_SRCDIR 200
2018 struct option long_options
[] =
2020 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
2021 {"debug", no_argument
, NULL
, 'd'},
2022 {"version", no_argument
, NULL
, 'V'},
2023 {"help", no_argument
, NULL
, 'h'},
2024 {0, no_argument
, NULL
, 0}
2028 print_version (void)
2030 printf ("%s: version 1.0\n", program_name
);
2035 usage (FILE * stream
, int status
)
2037 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2043 main (int argc
, char **argv
)
2045 extern int chdir (char *);
2046 char *srcdir
= NULL
;
2048 unsigned int i
, cpumax
;
2051 program_name
= *argv
;
2052 xmalloc_set_program_name (program_name
);
2054 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2079 if (chdir (srcdir
) != 0)
2080 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2081 srcdir
, xstrerror (errno
));
2083 /* cpu_flags isn't sorted by position. */
2085 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2086 if (cpu_flags
[i
].position
> cpumax
)
2087 cpumax
= cpu_flags
[i
].position
;
2089 /* Check the unused bitfield in i386_cpu_flags. */
2091 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2093 if ((cpumax
- 1) != CpuMax
)
2094 fail (_("CpuMax != %d!\n"), cpumax
);
2096 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2098 if (cpumax
!= CpuMax
)
2099 fail (_("CpuMax != %d!\n"), cpumax
);
2101 c
= CpuNumOfBits
- CpuMax
- 1;
2103 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2106 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2108 /* Check the unused bitfield in i386_operand_type. */
2110 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2113 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2116 c
= OTNumOfBits
- OTNum
;
2118 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2121 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2124 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2125 sizeof (opcode_modifiers
[0]), compare
);
2127 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2128 sizeof (operand_types
[0]), compare
);
2130 table
= fopen ("i386-tbl.h", "w");
2132 fail (_("can't create i386-tbl.h, errno = %s\n"),
2135 process_copyright (table
);
2137 process_i386_opcodes (table
);
2138 process_i386_registers (table
);
2139 process_i386_initializers ();