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 const struct template *next
;
827 const struct template_instance
*instances
;
828 const struct template_param
*params
;
831 static const 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
);
1115 adjust_broadcast_modifier (char **opnd
)
1117 char *str
, *next
, *last
, *op
;
1118 int bcst_type
= INT_MAX
;
1120 /* Skip the immediate operand. */
1122 if (strcasecmp(op
, "Imm8") == 0)
1126 last
= op
+ strlen (op
);
1127 for (next
= op
; next
&& next
< last
; )
1129 str
= next_field (next
, '|', &next
, last
);
1132 if (strcasecmp(str
, "Byte") == 0)
1134 /* The smalest broadcast type, no need to check
1136 bcst_type
= BYTE_BROADCAST
;
1139 else if (strcasecmp(str
, "Word") == 0)
1141 if (bcst_type
> WORD_BROADCAST
)
1142 bcst_type
= WORD_BROADCAST
;
1144 else if (strcasecmp(str
, "Dword") == 0)
1146 if (bcst_type
> DWORD_BROADCAST
)
1147 bcst_type
= DWORD_BROADCAST
;
1149 else if (strcasecmp(str
, "Qword") == 0)
1151 if (bcst_type
> QWORD_BROADCAST
)
1152 bcst_type
= QWORD_BROADCAST
;
1158 if (bcst_type
== INT_MAX
)
1159 fail (_("unknown broadcast operand: %s\n"), op
);
1165 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
1166 unsigned int prefix
, char **opnd
, int lineno
)
1168 char *str
, *next
, *last
;
1169 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1171 active_isstring
= 0;
1173 /* Copy the default opcode modifier. */
1174 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1176 if (strcmp (mod
, "0"))
1178 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1180 last
= mod
+ strlen (mod
);
1181 for (next
= mod
; next
&& next
< last
; )
1183 str
= next_field (next
, '|', &next
, last
);
1187 if (strcasecmp(str
, "Broadcast") == 0)
1188 val
= adjust_broadcast_modifier (opnd
);
1190 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1192 if (strcasecmp(str
, "IsString") == 0)
1193 active_isstring
= 1;
1195 if (strcasecmp(str
, "W") == 0)
1198 if (strcasecmp(str
, "No_bSuf") == 0)
1200 if (strcasecmp(str
, "No_wSuf") == 0)
1202 if (strcasecmp(str
, "No_lSuf") == 0)
1204 if (strcasecmp(str
, "No_qSuf") == 0)
1211 if (!modifiers
[OpcodeSpace
].value
)
1212 modifiers
[OpcodeSpace
].value
= space
;
1213 else if (modifiers
[OpcodeSpace
].value
!= space
)
1214 fail (_("%s:%d: Conflicting opcode space specifications\n"),
1218 _("%s:%d: Warning: redundant opcode space specification\n"),
1224 if (!modifiers
[OpcodePrefix
].value
)
1225 modifiers
[OpcodePrefix
].value
= prefix
;
1226 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1227 fail (_("%s:%d: Conflicting prefix specifications\n"),
1231 _("%s:%d: Warning: redundant prefix specification\n"),
1235 if (have_w
&& !bwlq_suf
)
1236 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1237 if (have_w
&& !(bwlq_suf
& 1))
1238 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1240 if (have_w
&& !(bwlq_suf
& ~1))
1242 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1245 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1255 output_operand_type (FILE *table
, enum operand_class
class,
1256 enum operand_instance instance
,
1257 const bitfield
*types
, unsigned int size
,
1258 enum stage stage
, const char *indent
)
1262 fprintf (table
, "{ { %d, %d, ", class, instance
);
1264 for (i
= 0; i
< size
- 1; i
++)
1266 if (((i
+ 3) % 20) != 0)
1267 fprintf (table
, "%d, ", types
[i
].value
);
1269 fprintf (table
, "%d,", types
[i
].value
);
1270 if (((i
+ 3) % 20) == 0)
1272 /* We need \\ for macro. */
1273 if (stage
== stage_macros
)
1274 fprintf (table
, " \\\n%s", indent
);
1276 fprintf (table
, "\n%s", indent
);
1280 fprintf (table
, "%d } }", types
[i
].value
);
1284 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1285 const char *indent
, int lineno
)
1287 char *str
, *next
, *last
;
1288 enum operand_class
class = ClassNone
;
1289 enum operand_instance instance
= InstanceNone
;
1290 bitfield types
[ARRAY_SIZE (operand_types
)];
1292 /* Copy the default operand type. */
1293 memcpy (types
, operand_types
, sizeof (types
));
1295 if (strcmp (op
, "0"))
1299 last
= op
+ strlen (op
);
1300 for (next
= op
; next
&& next
< last
; )
1302 str
= next_field (next
, '|', &next
, last
);
1307 if (!strncmp(str
, "Class=", 6))
1309 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1310 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1312 class = operand_classes
[i
].value
;
1318 if (str
&& !strncmp(str
, "Instance=", 9))
1320 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1321 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1323 instance
= operand_instances
[i
].value
;
1331 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1332 if (strcasecmp(str
, "BaseIndex") == 0)
1337 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1339 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1340 if (!active_cpu_flags
.bitfield
.cpu64
1341 && !active_cpu_flags
.bitfield
.cpumpx
)
1342 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1343 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1346 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1351 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1352 char *last
, int lineno
)
1354 unsigned int i
, length
, prefix
= 0, space
= 0;
1355 char *base_opcode
, *extension_opcode
, *end
;
1356 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1357 unsigned long long opcode
;
1359 /* Find base_opcode. */
1360 base_opcode
= next_field (str
, ',', &str
, last
);
1362 /* Find extension_opcode. */
1363 extension_opcode
= next_field (str
, ',', &str
, last
);
1365 /* Find cpu_flags. */
1366 cpu_flags
= next_field (str
, ',', &str
, last
);
1368 /* Find opcode_modifier. */
1369 opcode_modifier
= next_field (str
, ',', &str
, last
);
1371 /* Remove the first {. */
1372 str
= remove_leading_whitespaces (str
);
1375 str
= remove_leading_whitespaces (str
+ 1);
1376 remove_trailing_whitespaces (str
);
1378 /* Remove } and trailing white space. */
1380 if (!i
|| str
[i
- 1] != '}')
1383 remove_trailing_whitespaces (str
);
1386 operand_types
[i
= 0] = NULL
;
1389 last
= str
+ strlen (str
);
1391 /* Find operand_types. */
1392 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1396 operand_types
[i
] = NULL
;
1400 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1404 opcode
= strtoull (base_opcode
, &end
, 0);
1406 /* Determine opcode length. */
1407 for (length
= 1; length
< 8; ++length
)
1408 if (!(opcode
>> (8 * length
)))
1411 /* Transform prefixes encoded in the opcode into opcode modifier
1415 switch (opcode
>> (8 * length
- 8))
1417 case 0x66: prefix
= PREFIX_0X66
; break;
1418 case 0xF3: prefix
= PREFIX_0XF3
; break;
1419 case 0xF2: prefix
= PREFIX_0XF2
; break;
1423 opcode
&= (1ULL << (8 * --length
)) - 1;
1426 /* Transform opcode space encoded in the opcode into opcode modifier
1428 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1430 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1432 default: space
= SPACE_0F
; break;
1433 case 0x38: space
= SPACE_0F38
; break;
1434 case 0x3A: space
= SPACE_0F3A
; break;
1437 if (space
!= SPACE_0F
&& --length
== 1)
1438 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1439 filename
, lineno
, name
);
1440 opcode
&= (1ULL << (8 * --length
)) - 1;
1444 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1445 filename
, lineno
, name
, 2 * length
, opcode
);
1447 fprintf (table
, " { \"%s\", 0x%0*llx%s, %s, %lu,\n",
1448 name
, 2 * (int)length
, opcode
, end
, extension_opcode
, i
);
1450 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1451 operand_types
, lineno
);
1453 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1455 fprintf (table
, " { ");
1457 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1459 if (!operand_types
[i
])
1462 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1468 fprintf (table
, ",\n ");
1470 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1473 fprintf (table
, " } },\n");
1476 struct opcode_hash_entry
1478 struct opcode_hash_entry
*next
;
1484 /* Calculate the hash value of an opcode hash entry P. */
1487 opcode_hash_hash (const void *p
)
1489 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1490 return htab_hash_string (entry
->name
);
1493 /* Compare a string Q against an opcode hash entry P. */
1496 opcode_hash_eq (const void *p
, const void *q
)
1498 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1499 const char *name
= (const char *) q
;
1500 return strcmp (name
, entry
->name
) == 0;
1504 parse_template (char *buf
, int lineno
)
1506 char sep
, *end
, *name
;
1507 struct template *tmpl
= xmalloc (sizeof (*tmpl
));
1508 struct template_instance
*last_inst
= NULL
;
1510 buf
= remove_leading_whitespaces (buf
+ 1);
1511 end
= strchr (buf
, ':');
1513 fail ("%s: %d: missing ':'\n", filename
, lineno
);
1515 remove_trailing_whitespaces (buf
);
1518 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1519 tmpl
->name
= xstrdup (buf
);
1521 tmpl
->params
= NULL
;
1523 struct template_param
*param
;
1525 buf
= remove_leading_whitespaces (end
);
1526 end
= strpbrk (buf
, ":,");
1528 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1532 remove_trailing_whitespaces (buf
);
1534 param
= xmalloc (sizeof (*param
));
1535 param
->name
= xstrdup (buf
);
1536 param
->next
= tmpl
->params
;
1537 tmpl
->params
= param
;
1538 } while (sep
== ':');
1540 tmpl
->instances
= NULL
;
1542 struct template_instance
*inst
;
1544 const struct template_param
*param
;
1546 buf
= remove_leading_whitespaces (end
);
1547 end
= strpbrk (buf
, ",>");
1549 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1554 inst
= xmalloc (sizeof (*inst
));
1558 cur
= next_field (buf
, ':', &next
, end
);
1559 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1561 for (param
= tmpl
->params
; param
; param
= param
->next
)
1563 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1565 cur
= next_field (next
, ':', &next
, end
);
1567 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1568 arg
->val
= xstrdup (cur
);
1569 arg
->next
= inst
->args
;
1573 if (tmpl
->instances
)
1574 last_inst
->next
= inst
;
1576 tmpl
->instances
= inst
;
1578 } while (sep
== ',');
1580 buf
= remove_leading_whitespaces (end
);
1582 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1583 filename
, lineno
, buf
);
1585 tmpl
->next
= templates
;
1590 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1591 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1593 static unsigned int idx
, opcode_array_size
;
1594 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1595 struct opcode_hash_entry
**hash_slot
, **entry
;
1596 char *ptr1
= strchr(name
, '<'), *ptr2
;
1600 /* Get the slot in hash table. */
1601 hash_slot
= (struct opcode_hash_entry
**)
1602 htab_find_slot_with_hash (opcode_hash_table
, name
,
1603 htab_hash_string (name
),
1606 if (*hash_slot
== NULL
)
1608 /* It is the new one. Put it on opcode array. */
1609 if (idx
>= opcode_array_size
)
1611 /* Grow the opcode array when needed. */
1612 opcode_array_size
+= 1024;
1613 opcode_array
= (struct opcode_hash_entry
**)
1614 xrealloc (opcode_array
,
1615 sizeof (*opcode_array
) * opcode_array_size
);
1616 *opcode_array_p
= opcode_array
;
1619 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1620 xmalloc (sizeof (struct opcode_hash_entry
));
1621 opcode_array
[idx
]->next
= NULL
;
1622 opcode_array
[idx
]->name
= xstrdup (name
);
1623 opcode_array
[idx
]->opcode
= xstrdup (str
);
1624 opcode_array
[idx
]->lineno
= lineno
;
1625 *hash_slot
= opcode_array
[idx
];
1630 /* Append it to the existing one. */
1632 while ((*entry
) != NULL
)
1633 entry
= &(*entry
)->next
;
1634 *entry
= (struct opcode_hash_entry
*)
1635 xmalloc (sizeof (struct opcode_hash_entry
));
1636 (*entry
)->next
= NULL
;
1637 (*entry
)->name
= (*hash_slot
)->name
;
1638 (*entry
)->opcode
= xstrdup (str
);
1639 (*entry
)->lineno
= lineno
;
1642 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1643 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1646 const struct template *tmpl
;
1647 const struct template_instance
*inst
;
1650 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1651 remove_trailing_whitespaces (ptr1
);
1655 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1656 if (!strcmp(ptr1
, tmpl
->name
))
1659 fail ("reference to unknown template '%s'\n", ptr1
);
1661 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1663 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1664 char *str2
= xmalloc(2 * strlen(str
));
1667 strcpy (name2
, name
);
1668 strcat (name2
, inst
->name
);
1669 strcat (name2
, ptr2
);
1671 for (ptr1
= str2
, src
= str
; *src
; )
1673 const char *ident
= tmpl
->name
, *end
;
1674 const struct template_param
*param
;
1675 const struct template_arg
*arg
;
1677 if ((*ptr1
= *src
++) != '<')
1682 while (ISSPACE(*src
))
1684 while (*ident
&& *src
== *ident
)
1686 while (ISSPACE(*src
))
1688 if (*src
!= ':' || *ident
!= '\0')
1690 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1691 ptr1
+= ident
- tmpl
->name
;
1694 while (ISSPACE(*++src
))
1698 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1701 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1702 param
= param
->next
, arg
= arg
->next
)
1704 if (end
- src
== strlen (param
->name
)
1705 && !memcmp (src
, param
->name
, end
- src
))
1713 fail ("template '%s' has no parameter '%.*s'\n",
1714 tmpl
->name
, (int)(end
- src
), src
);
1716 while (ISSPACE(*src
))
1719 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1721 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1722 ptr1
+= strlen(arg
->val
);
1728 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1740 process_i386_opcodes (FILE *table
)
1745 char *str
, *p
, *last
, *name
;
1746 htab_t opcode_hash_table
;
1747 struct opcode_hash_entry
**opcode_array
= NULL
;
1748 int lineno
= 0, marker
= 0;
1750 filename
= "i386-opc.tbl";
1754 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1755 opcode_hash_eq
, NULL
,
1758 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1759 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1761 /* Put everything on opcode array. */
1764 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1769 p
= remove_leading_whitespaces (buf
);
1771 /* Skip comments. */
1772 str
= strstr (p
, "//");
1776 /* Remove trailing white spaces. */
1777 remove_trailing_whitespaces (p
);
1782 if (!strcmp("### MARKER ###", buf
))
1786 /* Since we ignore all included files (we only care about their
1787 #define-s here), we don't need to monitor filenames. The final
1788 line number directive is going to refer to the main source file
1793 p
= remove_leading_whitespaces (p
+ 1);
1794 if (!strncmp(p
, "line", 4))
1796 ln
= strtoul (p
, &end
, 10);
1797 if (ln
> 1 && ln
< INT_MAX
1798 && *remove_leading_whitespaces (end
) == '"')
1801 /* Ignore comments. */
1806 parse_template (p
, lineno
);
1814 last
= p
+ strlen (p
);
1817 name
= next_field (p
, ',', &str
, last
);
1819 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1823 /* Process opcode array. */
1824 for (j
= 0; j
< i
; j
++)
1826 struct opcode_hash_entry
*next
;
1828 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1832 lineno
= next
->lineno
;
1833 last
= str
+ strlen (str
);
1834 output_i386_opcode (table
, name
, str
, last
, lineno
);
1840 fprintf (table
, " { NULL, 0, 0, 0,\n");
1842 process_i386_opcode_modifier (table
, "0", 0, 0, NULL
, -1);
1844 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1846 fprintf (table
, " { ");
1847 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1848 fprintf (table
, " } }\n");
1850 fprintf (table
, "};\n");
1854 process_i386_registers (FILE *table
)
1858 char *str
, *p
, *last
;
1859 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1860 char *dw2_32_num
, *dw2_64_num
;
1863 filename
= "i386-reg.tbl";
1864 fp
= fopen (filename
, "r");
1866 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1869 fprintf (table
, "\n/* i386 register table. */\n\n");
1870 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1874 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1879 p
= remove_leading_whitespaces (buf
);
1881 /* Skip comments. */
1882 str
= strstr (p
, "//");
1886 /* Remove trailing white spaces. */
1887 remove_trailing_whitespaces (p
);
1892 fprintf (table
, "%s\n", p
);
1900 last
= p
+ strlen (p
);
1902 /* Find reg_name. */
1903 reg_name
= next_field (p
, ',', &str
, last
);
1905 /* Find reg_type. */
1906 reg_type
= next_field (str
, ',', &str
, last
);
1908 /* Find reg_flags. */
1909 reg_flags
= next_field (str
, ',', &str
, last
);
1912 reg_num
= next_field (str
, ',', &str
, last
);
1914 fprintf (table
, " { \"%s\",\n ", reg_name
);
1916 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1919 /* Find 32-bit Dwarf2 register number. */
1920 dw2_32_num
= next_field (str
, ',', &str
, last
);
1922 /* Find 64-bit Dwarf2 register number. */
1923 dw2_64_num
= next_field (str
, ',', &str
, last
);
1925 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1926 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1931 fprintf (table
, "};\n");
1933 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1937 process_i386_initializers (void)
1940 FILE *fp
= fopen ("i386-init.h", "w");
1944 fail (_("can't create i386-init.h, errno = %s\n"),
1947 process_copyright (fp
);
1949 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1951 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1952 init
= xstrdup (cpu_flag_init
[i
].init
);
1953 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1957 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1959 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1960 init
= xstrdup (operand_type_init
[i
].init
);
1961 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1969 /* Program options. */
1970 #define OPTION_SRCDIR 200
1972 struct option long_options
[] =
1974 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1975 {"debug", no_argument
, NULL
, 'd'},
1976 {"version", no_argument
, NULL
, 'V'},
1977 {"help", no_argument
, NULL
, 'h'},
1978 {0, no_argument
, NULL
, 0}
1982 print_version (void)
1984 printf ("%s: version 1.0\n", program_name
);
1989 usage (FILE * stream
, int status
)
1991 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1997 main (int argc
, char **argv
)
1999 extern int chdir (char *);
2000 char *srcdir
= NULL
;
2002 unsigned int i
, cpumax
;
2005 program_name
= *argv
;
2006 xmalloc_set_program_name (program_name
);
2008 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2033 if (chdir (srcdir
) != 0)
2034 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2035 srcdir
, xstrerror (errno
));
2037 /* cpu_flags isn't sorted by position. */
2039 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2040 if (cpu_flags
[i
].position
> cpumax
)
2041 cpumax
= cpu_flags
[i
].position
;
2043 /* Check the unused bitfield in i386_cpu_flags. */
2045 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2047 if ((cpumax
- 1) != CpuMax
)
2048 fail (_("CpuMax != %d!\n"), cpumax
);
2050 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2052 if (cpumax
!= CpuMax
)
2053 fail (_("CpuMax != %d!\n"), cpumax
);
2055 c
= CpuNumOfBits
- CpuMax
- 1;
2057 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2060 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2062 /* Check the unused bitfield in i386_operand_type. */
2064 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2067 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2070 c
= OTNumOfBits
- OTNum
;
2072 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2075 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2078 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2079 sizeof (opcode_modifiers
[0]), compare
);
2081 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2082 sizeof (operand_types
[0]), compare
);
2084 table
= fopen ("i386-tbl.h", "w");
2086 fail (_("can't create i386-tbl.h, errno = %s\n"),
2089 process_copyright (table
);
2091 process_i386_opcodes (table
);
2092 process_i386_registers (table
);
2093 process_i386_initializers ();