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",
305 "CPU_AMX_TILE_FLAGS|CpuAMX_INT8" },
306 { "CPU_AMX_BF16_FLAGS",
307 "CPU_AMX_TILE_FLAGS|CpuAMX_BF16" },
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
),
709 BITFIELD (AddrPrefixOpReg
),
714 BITFIELD (PseudoVexPrefix
),
718 BITFIELD (OpcodeSpace
),
719 BITFIELD (OpcodePrefix
),
720 BITFIELD (VexSources
),
725 BITFIELD (Broadcast
),
726 BITFIELD (StaticRounding
),
728 BITFIELD (Disp8MemShift
),
729 BITFIELD (NoDefMask
),
730 BITFIELD (ImplicitQuadGroup
),
731 BITFIELD (SwapSources
),
733 BITFIELD (ATTMnemonic
),
734 BITFIELD (ATTSyntax
),
735 BITFIELD (IntelSyntax
),
739 #define CLASS(n) #n, n
741 static const struct {
743 enum operand_class value
;
744 } operand_classes
[] = {
758 #define INSTANCE(n) #n, n
760 static const struct {
762 enum operand_instance value
;
763 } operand_instances
[] = {
772 static bitfield operand_types
[] =
781 BITFIELD (BaseIndex
),
796 BITFIELD (Unspecified
),
802 static const char *filename
;
803 static i386_cpu_flags active_cpu_flags
;
804 static int active_isstring
;
806 struct template_arg
{
807 const struct template_arg
*next
;
811 struct template_instance
{
812 const struct template_instance
*next
;
814 const struct template_arg
*args
;
817 struct template_param
{
818 const struct template_param
*next
;
823 struct template *next
;
825 const struct template_instance
*instances
;
826 const struct template_param
*params
;
829 static struct template *templates
;
832 compare (const void *x
, const void *y
)
834 const bitfield
*xp
= (const bitfield
*) x
;
835 const bitfield
*yp
= (const bitfield
*) y
;
836 return xp
->position
- yp
->position
;
840 fail (const char *message
, ...)
844 va_start (args
, message
);
845 fprintf (stderr
, _("%s: error: "), program_name
);
846 vfprintf (stderr
, message
, args
);
852 process_copyright (FILE *fp
)
854 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
855 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
857 This file is part of the GNU opcodes library.\n\
859 This library is free software; you can redistribute it and/or modify\n\
860 it under the terms of the GNU General Public License as published by\n\
861 the Free Software Foundation; either version 3, or (at your option)\n\
862 any later version.\n\
864 It is distributed in the hope that it will be useful, but WITHOUT\n\
865 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
866 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
867 License for more details.\n\
869 You should have received a copy of the GNU General Public License\n\
870 along with this program; if not, write to the Free Software\n\
871 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
872 MA 02110-1301, USA. */\n");
875 /* Remove leading white spaces. */
878 remove_leading_whitespaces (char *str
)
880 while (ISSPACE (*str
))
885 /* Remove trailing white spaces. */
888 remove_trailing_whitespaces (char *str
)
890 size_t last
= strlen (str
);
898 if (ISSPACE (str
[last
]))
906 /* Find next field separated by SEP and terminate it. Return a
907 pointer to the one after it. */
910 next_field (char *str
, char sep
, char **next
, char *last
)
914 p
= remove_leading_whitespaces (str
);
915 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
918 remove_trailing_whitespaces (p
);
928 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
931 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
934 char *str
, *next
, *last
;
937 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
938 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
940 /* Turn on selective bits. */
941 char *init
= xstrdup (cpu_flag_init
[i
].init
);
942 last
= init
+ strlen (init
);
943 for (next
= init
; next
&& next
< last
; )
945 str
= next_field (next
, '|', &next
, last
);
947 set_bitfield (str
, array
, 1, size
, lineno
);
957 set_bitfield (char *f
, bitfield
*array
, int value
,
958 unsigned int size
, int lineno
)
962 /* Ignore empty fields; they may result from template expansions. */
966 for (i
= 0; i
< size
; i
++)
967 if (strcasecmp (array
[i
].name
, f
) == 0)
969 array
[i
].value
= value
;
975 const char *v
= strchr (f
, '=');
982 for (i
= 0; i
< size
; i
++)
983 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
985 value
= strtol (v
+ 1, &end
, 0);
988 array
[i
].value
= value
;
996 /* Handle CPU_XXX_FLAGS. */
997 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
1001 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
1003 fail (_("unknown bitfield: %s\n"), f
);
1007 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
1008 int macro
, const char *comma
, const char *indent
)
1012 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
1014 fprintf (table
, "%s{ { ", indent
);
1016 for (i
= 0; i
< size
- 1; i
++)
1018 if (((i
+ 1) % 20) != 0)
1019 fprintf (table
, "%d, ", flags
[i
].value
);
1021 fprintf (table
, "%d,", flags
[i
].value
);
1022 if (((i
+ 1) % 20) == 0)
1024 /* We need \\ for macro. */
1026 fprintf (table
, " \\\n %s", indent
);
1028 fprintf (table
, "\n %s", indent
);
1031 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
1034 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
1038 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
1039 const char *comma
, const char *indent
,
1042 char *str
, *next
= flag
, *last
;
1045 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
1047 /* Copy the default cpu flags. */
1048 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
1052 last
= flag
+ strlen (flag
);
1059 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
1066 /* First we turn on everything except for cpu64, cpuno64, and - if
1067 present - the padding field. */
1068 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1069 if (flags
[i
].position
< Cpu64
)
1072 /* Turn off selective bits. */
1076 if (strcmp (flag
, "0"))
1078 /* Turn on/off selective bits. */
1079 last
= flag
+ strlen (flag
);
1080 for (; next
&& next
< last
; )
1082 str
= next_field (next
, '|', &next
, last
);
1084 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
1088 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1093 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1097 fprintf (table
, " { ");
1099 for (i
= 0; i
< size
- 1; i
++)
1101 if (((i
+ 1) % 20) != 0)
1102 fprintf (table
, "%d, ", modifier
[i
].value
);
1104 fprintf (table
, "%d,", modifier
[i
].value
);
1105 if (((i
+ 1) % 20) == 0)
1106 fprintf (table
, "\n ");
1109 fprintf (table
, "%d },\n", modifier
[i
].value
);
1112 /* Returns LOG2 of element size. */
1114 get_element_size (char **opnd
, int lineno
)
1116 char *str
, *next
, *last
, *op
;
1117 const char *full
= opnd
[0];
1118 int elem_size
= INT_MAX
;
1120 /* Find the memory operand. */
1121 while (full
!= NULL
&& strstr(full
, "BaseIndex") == NULL
)
1124 fail (_("%s: %d: no memory operand\n"), filename
, lineno
);
1126 op
= xstrdup (full
);
1127 last
= op
+ strlen (op
);
1128 for (next
= op
; next
&& next
< last
; )
1130 str
= next_field (next
, '|', &next
, last
);
1133 if (strcasecmp(str
, "Byte") == 0)
1135 /* The smallest element size, no need to check
1140 else if (strcasecmp(str
, "Word") == 0)
1145 else if (strcasecmp(str
, "Dword") == 0)
1150 else if (strcasecmp(str
, "Qword") == 0)
1159 if (elem_size
== INT_MAX
)
1160 fail (_("%s: %d: unknown element size: %s\n"), filename
, lineno
, full
);
1166 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
1167 unsigned int prefix
, char **opnd
, int lineno
)
1169 char *str
, *next
, *last
;
1170 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1172 active_isstring
= 0;
1174 /* Copy the default opcode modifier. */
1175 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1177 if (strcmp (mod
, "0"))
1179 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1181 last
= mod
+ strlen (mod
);
1182 for (next
= mod
; next
&& next
< last
; )
1184 str
= next_field (next
, '|', &next
, last
);
1188 if (strcasecmp(str
, "Broadcast") == 0)
1189 val
= get_element_size (opnd
, lineno
) + BYTE_BROADCAST
;
1190 else if (strcasecmp(str
, "Disp8MemShift") == 0)
1191 val
= get_element_size (opnd
, lineno
);
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 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1349 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1354 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1355 char *last
, int lineno
)
1357 unsigned int i
, length
, prefix
= 0, space
= 0;
1358 char *base_opcode
, *extension_opcode
, *end
;
1359 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1360 unsigned long long opcode
;
1362 /* Find base_opcode. */
1363 base_opcode
= next_field (str
, ',', &str
, last
);
1365 /* Find extension_opcode. */
1366 extension_opcode
= next_field (str
, ',', &str
, last
);
1368 /* Find cpu_flags. */
1369 cpu_flags
= next_field (str
, ',', &str
, last
);
1371 /* Find opcode_modifier. */
1372 opcode_modifier
= next_field (str
, ',', &str
, last
);
1374 /* Remove the first {. */
1375 str
= remove_leading_whitespaces (str
);
1378 str
= remove_leading_whitespaces (str
+ 1);
1379 remove_trailing_whitespaces (str
);
1381 /* Remove } and trailing white space. */
1383 if (!i
|| str
[i
- 1] != '}')
1386 remove_trailing_whitespaces (str
);
1389 operand_types
[i
= 0] = NULL
;
1392 last
= str
+ strlen (str
);
1394 /* Find operand_types. */
1395 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1399 operand_types
[i
] = NULL
;
1403 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1407 opcode
= strtoull (base_opcode
, &end
, 0);
1409 /* Determine opcode length. */
1410 for (length
= 1; length
< 8; ++length
)
1411 if (!(opcode
>> (8 * length
)))
1414 /* Transform prefixes encoded in the opcode into opcode modifier
1418 switch (opcode
>> (8 * length
- 8))
1420 case 0x66: prefix
= PREFIX_0X66
; break;
1421 case 0xF3: prefix
= PREFIX_0XF3
; break;
1422 case 0xF2: prefix
= PREFIX_0XF2
; break;
1426 opcode
&= (1ULL << (8 * --length
)) - 1;
1429 /* Transform opcode space encoded in the opcode into opcode modifier
1431 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1433 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1435 default: space
= SPACE_0F
; break;
1436 case 0x38: space
= SPACE_0F38
; break;
1437 case 0x3A: space
= SPACE_0F3A
; break;
1440 if (space
!= SPACE_0F
&& --length
== 1)
1441 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1442 filename
, lineno
, name
);
1443 opcode
&= (1ULL << (8 * --length
)) - 1;
1447 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1448 filename
, lineno
, name
, 2 * length
, opcode
);
1450 fprintf (table
, " { \"%s\", 0x%0*llx%s, %lu, %s,\n",
1451 name
, 2 * (int)length
, opcode
, end
, i
, extension_opcode
);
1453 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1454 operand_types
, lineno
);
1456 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1458 fprintf (table
, " { ");
1460 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1462 if (!operand_types
[i
])
1465 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1471 fprintf (table
, ",\n ");
1473 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1476 fprintf (table
, " } },\n");
1479 struct opcode_hash_entry
1481 struct opcode_hash_entry
*next
;
1487 /* Calculate the hash value of an opcode hash entry P. */
1490 opcode_hash_hash (const void *p
)
1492 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1493 return htab_hash_string (entry
->name
);
1496 /* Compare a string Q against an opcode hash entry P. */
1499 opcode_hash_eq (const void *p
, const void *q
)
1501 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1502 const char *name
= (const char *) q
;
1503 return strcmp (name
, entry
->name
) == 0;
1507 parse_template (char *buf
, int lineno
)
1509 char sep
, *end
, *name
;
1510 struct template *tmpl
;
1511 struct template_instance
*last_inst
= NULL
;
1513 buf
= remove_leading_whitespaces (buf
+ 1);
1514 end
= strchr (buf
, ':');
1517 struct template *prev
= NULL
;
1519 end
= strchr (buf
, '>');
1521 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1522 if (*remove_leading_whitespaces (end
+ 1))
1523 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1525 remove_trailing_whitespaces (buf
);
1526 /* Don't bother freeing the various structures. */
1527 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1528 if (!strcmp (buf
, tmpl
->name
))
1531 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1533 prev
->next
= tmpl
->next
;
1535 templates
= tmpl
->next
;
1539 remove_trailing_whitespaces (buf
);
1542 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1543 tmpl
= xmalloc (sizeof (*tmpl
));
1544 tmpl
->name
= xstrdup (buf
);
1546 tmpl
->params
= NULL
;
1548 struct template_param
*param
;
1550 buf
= remove_leading_whitespaces (end
);
1551 end
= strpbrk (buf
, ":,");
1553 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1557 remove_trailing_whitespaces (buf
);
1559 param
= xmalloc (sizeof (*param
));
1560 param
->name
= xstrdup (buf
);
1561 param
->next
= tmpl
->params
;
1562 tmpl
->params
= param
;
1563 } while (sep
== ':');
1565 tmpl
->instances
= NULL
;
1567 struct template_instance
*inst
;
1569 const struct template_param
*param
;
1571 buf
= remove_leading_whitespaces (end
);
1572 end
= strpbrk (buf
, ",>");
1574 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1579 inst
= xmalloc (sizeof (*inst
));
1583 cur
= next_field (buf
, ':', &next
, end
);
1584 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1586 for (param
= tmpl
->params
; param
; param
= param
->next
)
1588 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1590 cur
= next_field (next
, ':', &next
, end
);
1592 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1593 arg
->val
= xstrdup (cur
);
1594 arg
->next
= inst
->args
;
1598 if (tmpl
->instances
)
1599 last_inst
->next
= inst
;
1601 tmpl
->instances
= inst
;
1603 } while (sep
== ',');
1605 buf
= remove_leading_whitespaces (end
);
1607 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1608 filename
, lineno
, buf
);
1610 tmpl
->next
= templates
;
1615 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1616 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1618 static unsigned int idx
, opcode_array_size
;
1619 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1620 struct opcode_hash_entry
**hash_slot
, **entry
;
1621 char *ptr1
= strchr(name
, '<'), *ptr2
;
1625 /* Get the slot in hash table. */
1626 hash_slot
= (struct opcode_hash_entry
**)
1627 htab_find_slot_with_hash (opcode_hash_table
, name
,
1628 htab_hash_string (name
),
1631 if (*hash_slot
== NULL
)
1633 /* It is the new one. Put it on opcode array. */
1634 if (idx
>= opcode_array_size
)
1636 /* Grow the opcode array when needed. */
1637 opcode_array_size
+= 1024;
1638 opcode_array
= (struct opcode_hash_entry
**)
1639 xrealloc (opcode_array
,
1640 sizeof (*opcode_array
) * opcode_array_size
);
1641 *opcode_array_p
= opcode_array
;
1644 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1645 xmalloc (sizeof (struct opcode_hash_entry
));
1646 opcode_array
[idx
]->next
= NULL
;
1647 opcode_array
[idx
]->name
= xstrdup (name
);
1648 opcode_array
[idx
]->opcode
= xstrdup (str
);
1649 opcode_array
[idx
]->lineno
= lineno
;
1650 *hash_slot
= opcode_array
[idx
];
1655 /* Append it to the existing one. */
1657 while ((*entry
) != NULL
)
1658 entry
= &(*entry
)->next
;
1659 *entry
= (struct opcode_hash_entry
*)
1660 xmalloc (sizeof (struct opcode_hash_entry
));
1661 (*entry
)->next
= NULL
;
1662 (*entry
)->name
= (*hash_slot
)->name
;
1663 (*entry
)->opcode
= xstrdup (str
);
1664 (*entry
)->lineno
= lineno
;
1667 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1668 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1671 const struct template *tmpl
;
1672 const struct template_instance
*inst
;
1675 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1676 remove_trailing_whitespaces (ptr1
);
1680 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1681 if (!strcmp(ptr1
, tmpl
->name
))
1684 fail ("reference to unknown template '%s'\n", ptr1
);
1686 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1688 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1689 char *str2
= xmalloc(2 * strlen(str
));
1692 strcpy (name2
, name
);
1693 strcat (name2
, inst
->name
);
1694 strcat (name2
, ptr2
);
1696 for (ptr1
= str2
, src
= str
; *src
; )
1698 const char *ident
= tmpl
->name
, *end
;
1699 const struct template_param
*param
;
1700 const struct template_arg
*arg
;
1702 if ((*ptr1
= *src
++) != '<')
1707 while (ISSPACE(*src
))
1709 while (*ident
&& *src
== *ident
)
1711 while (ISSPACE(*src
))
1713 if (*src
!= ':' || *ident
!= '\0')
1715 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1716 ptr1
+= ident
- tmpl
->name
;
1719 while (ISSPACE(*++src
))
1723 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1726 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1727 param
= param
->next
, arg
= arg
->next
)
1729 if (end
- src
== strlen (param
->name
)
1730 && !memcmp (src
, param
->name
, end
- src
))
1738 fail ("template '%s' has no parameter '%.*s'\n",
1739 tmpl
->name
, (int)(end
- src
), src
);
1741 while (ISSPACE(*src
))
1744 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1746 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1747 ptr1
+= strlen(arg
->val
);
1753 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1765 process_i386_opcodes (FILE *table
)
1770 char *str
, *p
, *last
, *name
;
1771 htab_t opcode_hash_table
;
1772 struct opcode_hash_entry
**opcode_array
= NULL
;
1773 int lineno
= 0, marker
= 0;
1775 filename
= "i386-opc.tbl";
1779 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1780 opcode_hash_eq
, NULL
,
1783 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1784 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1786 /* Put everything on opcode array. */
1789 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1792 p
= remove_leading_whitespaces (buf
);
1798 /* Skip comments. */
1799 str
= strstr (p
, "//");
1803 remove_trailing_whitespaces (p
);
1807 /* Look for line continuation character. */
1808 remove_trailing_whitespaces (p
);
1810 if (!j
|| buf
[j
- 1] != '+')
1812 if (j
>= sizeof (buf
) - 1)
1813 fail (_("%s: %d: (continued) line too long\n"), filename
, lineno
);
1815 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1817 fprintf (stderr
, "%s: Line continuation on last line?\n",
1826 if (!strcmp("### MARKER ###", buf
))
1830 /* Since we ignore all included files (we only care about their
1831 #define-s here), we don't need to monitor filenames. The final
1832 line number directive is going to refer to the main source file
1837 p
= remove_leading_whitespaces (p
+ 1);
1838 if (!strncmp(p
, "line", 4))
1840 ln
= strtoul (p
, &end
, 10);
1841 if (ln
> 1 && ln
< INT_MAX
1842 && *remove_leading_whitespaces (end
) == '"')
1845 /* Ignore comments. */
1850 parse_template (p
, lineno
);
1858 last
= p
+ strlen (p
);
1861 name
= next_field (p
, ',', &str
, last
);
1863 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1867 /* Process opcode array. */
1868 for (j
= 0; j
< i
; j
++)
1870 struct opcode_hash_entry
*next
;
1872 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1876 lineno
= next
->lineno
;
1877 last
= str
+ strlen (str
);
1878 output_i386_opcode (table
, name
, str
, last
, lineno
);
1884 fprintf (table
, " { NULL, 0, 0, 0,\n");
1886 process_i386_opcode_modifier (table
, "0", 0, 0, NULL
, -1);
1888 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1890 fprintf (table
, " { ");
1891 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1892 fprintf (table
, " } }\n");
1894 fprintf (table
, "};\n");
1898 process_i386_registers (FILE *table
)
1902 char *str
, *p
, *last
;
1903 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1904 char *dw2_32_num
, *dw2_64_num
;
1907 filename
= "i386-reg.tbl";
1908 fp
= fopen (filename
, "r");
1910 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1913 fprintf (table
, "\n/* i386 register table. */\n\n");
1914 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1918 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1923 p
= remove_leading_whitespaces (buf
);
1925 /* Skip comments. */
1926 str
= strstr (p
, "//");
1930 /* Remove trailing white spaces. */
1931 remove_trailing_whitespaces (p
);
1936 fprintf (table
, "%s\n", p
);
1944 last
= p
+ strlen (p
);
1946 /* Find reg_name. */
1947 reg_name
= next_field (p
, ',', &str
, last
);
1949 /* Find reg_type. */
1950 reg_type
= next_field (str
, ',', &str
, last
);
1952 /* Find reg_flags. */
1953 reg_flags
= next_field (str
, ',', &str
, last
);
1956 reg_num
= next_field (str
, ',', &str
, last
);
1958 fprintf (table
, " { \"%s\",\n ", reg_name
);
1960 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1963 /* Find 32-bit Dwarf2 register number. */
1964 dw2_32_num
= next_field (str
, ',', &str
, last
);
1966 /* Find 64-bit Dwarf2 register number. */
1967 dw2_64_num
= next_field (str
, ',', &str
, last
);
1969 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1970 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1975 fprintf (table
, "};\n");
1977 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1981 process_i386_initializers (void)
1984 FILE *fp
= fopen ("i386-init.h", "w");
1988 fail (_("can't create i386-init.h, errno = %s\n"),
1991 process_copyright (fp
);
1993 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1995 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1996 init
= xstrdup (cpu_flag_init
[i
].init
);
1997 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
2001 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
2003 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
2004 init
= xstrdup (operand_type_init
[i
].init
);
2005 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
2013 /* Program options. */
2014 #define OPTION_SRCDIR 200
2016 struct option long_options
[] =
2018 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
2019 {"debug", no_argument
, NULL
, 'd'},
2020 {"version", no_argument
, NULL
, 'V'},
2021 {"help", no_argument
, NULL
, 'h'},
2022 {0, no_argument
, NULL
, 0}
2026 print_version (void)
2028 printf ("%s: version 1.0\n", program_name
);
2033 usage (FILE * stream
, int status
)
2035 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2041 main (int argc
, char **argv
)
2043 extern int chdir (char *);
2044 char *srcdir
= NULL
;
2046 unsigned int i
, cpumax
;
2049 program_name
= *argv
;
2050 xmalloc_set_program_name (program_name
);
2052 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2077 if (chdir (srcdir
) != 0)
2078 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2079 srcdir
, xstrerror (errno
));
2081 /* cpu_flags isn't sorted by position. */
2083 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2084 if (cpu_flags
[i
].position
> cpumax
)
2085 cpumax
= cpu_flags
[i
].position
;
2087 /* Check the unused bitfield in i386_cpu_flags. */
2089 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2091 if ((cpumax
- 1) != CpuMax
)
2092 fail (_("CpuMax != %d!\n"), cpumax
);
2094 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2096 if (cpumax
!= CpuMax
)
2097 fail (_("CpuMax != %d!\n"), cpumax
);
2099 c
= CpuNumOfBits
- CpuMax
- 1;
2101 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2104 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2106 /* Check the unused bitfield in i386_operand_type. */
2108 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2111 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2114 c
= OTNumOfBits
- OTNum
;
2116 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2119 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2122 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2123 sizeof (opcode_modifiers
[0]), compare
);
2125 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2126 sizeof (operand_types
[0]), compare
);
2128 table
= fopen ("i386-tbl.h", "w");
2130 fail (_("can't create i386-tbl.h, errno = %s\n"),
2133 process_copyright (table
);
2135 process_i386_opcodes (table
);
2136 process_i386_registers (table
);
2137 process_i386_initializers ();