1 /* Copyright (C) 2007-2020 Free Software Foundation, Inc.
3 This file is part of the GNU opcodes library.
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
10 It is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13 License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18 MA 02110-1301, USA. */
24 #include "libiberty.h"
26 #include "safe-ctype.h"
31 #define _(String) gettext (String)
33 /* Build-time checks are preferrable over runtime ones. Use this construct
34 in preference where possible. */
35 #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
37 static const char *program_name
= NULL
;
40 typedef struct initializer
46 static initializer cpu_flag_init
[] =
48 { "CPU_UNKNOWN_FLAGS",
49 "~(CpuL1OM|CpuK1OM)" },
50 { "CPU_GENERIC32_FLAGS",
51 "Cpu186|Cpu286|Cpu386" },
52 { "CPU_GENERIC64_FLAGS",
53 "CPU_PENTIUMPRO_FLAGS|CpuClflush|CpuSYSCALL|CPU_MMX_FLAGS|CPU_SSE2_FLAGS|CpuLM" },
59 "CPU_I186_FLAGS|Cpu286" },
61 "CPU_I286_FLAGS|Cpu386" },
63 "CPU_I386_FLAGS|Cpu486" },
65 "CPU_I486_FLAGS|Cpu387|Cpu586" },
67 "CPU_I586_FLAGS|Cpu686|Cpu687|CpuCMOV|CpuFXSR" },
68 { "CPU_PENTIUMPRO_FLAGS",
69 "CPU_I686_FLAGS|CpuNop" },
71 "CPU_PENTIUMPRO_FLAGS|CPU_MMX_FLAGS" },
73 "CPU_P2_FLAGS|CPU_SSE_FLAGS" },
75 "CPU_P3_FLAGS|CpuClflush|CPU_SSE2_FLAGS" },
77 "CPU_GENERIC64_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
79 "CPU_P4_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
81 "CPU_NOCONA_FLAGS|CPU_SSSE3_FLAGS" },
83 "CPU_CORE2_FLAGS|CPU_SSE4_2_FLAGS|CpuRdtscp" },
85 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CPU_MMX_FLAGS" },
87 "CPU_K6_FLAGS|Cpu3dnow" },
89 "CPU_K6_2_FLAGS|Cpu686|Cpu687|CpuNop|Cpu3dnowA" },
91 "CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
92 { "CPU_AMDFAM10_FLAGS",
93 "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuLZCNT|CpuPOPCNT" },
95 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuLZCNT|CpuPOPCNT|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW" },
97 "CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
99 "CPU_BDVER2_FLAGS|CpuXsaveopt|CpuFSGSBase" },
100 { "CPU_BDVER4_FLAGS",
101 "CPU_BDVER3_FLAGS|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuMWAITX" },
102 { "CPU_ZNVER1_FLAGS",
103 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_AVX2_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW|CpuFMA|CpuBMI|CpuF16C|CpuXsaveopt|CpuFSGSBase|CpuMovbe|CpuBMI2|CpuRdRnd|CpuADX|CpuRdSeed|CpuSMAP|CpuSHA|CpuXSAVEC|CpuXSAVES|CpuClflushOpt|CpuCLZERO|CpuMWAITX" },
104 { "CPU_ZNVER2_FLAGS",
105 "CPU_ZNVER1_FLAGS|CpuCLWB|CpuRDPID|CpuRDPRU|CpuMCOMMIT|CpuWBNOINVD" },
106 { "CPU_BTVER1_FLAGS",
107 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME" },
108 { "CPU_BTVER2_FLAGS",
109 "CPU_BTVER1_FLAGS|CPU_AVX_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuMovbe|CpuXsaveopt|CpuPRFCHW" },
117 "CPU_387_FLAGS|Cpu687" },
122 { "CPU_CLFLUSH_FLAGS",
126 { "CPU_SYSCALL_FLAGS",
133 "CPU_SSE_FLAGS|CpuSSE2" },
135 "CPU_SSE2_FLAGS|CpuSSE3" },
137 "CPU_SSE3_FLAGS|CpuSSSE3" },
138 { "CPU_SSE4_1_FLAGS",
139 "CPU_SSSE3_FLAGS|CpuSSE4_1" },
140 { "CPU_SSE4_2_FLAGS",
141 "CPU_SSE4_1_FLAGS|CpuSSE4_2|CpuPOPCNT" },
148 { "CPU_XSAVEOPT_FLAGS",
149 "CPU_XSAVE_FLAGS|CpuXsaveopt" },
151 "CPU_SSE2_FLAGS|CpuAES" },
152 { "CPU_PCLMUL_FLAGS",
153 "CPU_SSE2_FLAGS|CpuPCLMUL" },
155 "CPU_AVX_FLAGS|CpuFMA" },
157 "CPU_AVX_FLAGS|CpuFMA4" },
159 "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
161 "CPU_XSAVE_FLAGS|CpuLWP" },
170 { "CPU_RDTSCP_FLAGS",
174 { "CPU_FSGSBASE_FLAGS",
179 "CPU_AVX_FLAGS|CpuF16C" },
184 { "CPU_POPCNT_FLAGS",
190 { "CPU_INVPCID_FLAGS",
192 { "CPU_VMFUNC_FLAGS",
195 "CPU_MMX_FLAGS|Cpu3dnow" },
196 { "CPU_3DNOWA_FLAGS",
197 "CPU_3DNOW_FLAGS|Cpu3dnowA" },
198 { "CPU_PADLOCK_FLAGS",
203 "CPU_SSE3_FLAGS|CpuSSE4a" },
205 "CpuLZCNT|CpuPOPCNT" },
207 "CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
209 "CPU_AVX_FLAGS|CpuAVX2" },
210 { "CPU_AVX512F_FLAGS",
211 "CPU_AVX2_FLAGS|CpuAVX512F" },
212 { "CPU_AVX512CD_FLAGS",
213 "CPU_AVX512F_FLAGS|CpuAVX512CD" },
214 { "CPU_AVX512ER_FLAGS",
215 "CPU_AVX512F_FLAGS|CpuAVX512ER" },
216 { "CPU_AVX512PF_FLAGS",
217 "CPU_AVX512F_FLAGS|CpuAVX512PF" },
218 { "CPU_AVX512DQ_FLAGS",
219 "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
220 { "CPU_AVX512BW_FLAGS",
221 "CPU_AVX512F_FLAGS|CpuAVX512BW" },
222 { "CPU_AVX512VL_FLAGS",
223 "CPU_AVX512F_FLAGS|CpuAVX512VL" },
224 { "CPU_AVX512IFMA_FLAGS",
225 "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
226 { "CPU_AVX512VBMI_FLAGS",
227 "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
228 { "CPU_AVX512_4FMAPS_FLAGS",
229 "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
230 { "CPU_AVX512_4VNNIW_FLAGS",
231 "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
232 { "CPU_AVX512_VPOPCNTDQ_FLAGS",
233 "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
234 { "CPU_AVX512_VBMI2_FLAGS",
235 "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
236 { "CPU_AVX512_VNNI_FLAGS",
237 "CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
238 { "CPU_AVX512_BITALG_FLAGS",
239 "CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
240 { "CPU_AVX512_BF16_FLAGS",
241 "CPU_AVX512F_FLAGS|CpuAVX512_BF16" },
247 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
250 { "CPU_RDSEED_FLAGS",
252 { "CPU_PRFCHW_FLAGS",
257 "CPU_XSAVE_FLAGS|CpuMPX" },
259 "CPU_SSE2_FLAGS|CpuSHA" },
260 { "CPU_CLFLUSHOPT_FLAGS",
262 { "CPU_XSAVES_FLAGS",
263 "CPU_XSAVE_FLAGS|CpuXSAVES" },
264 { "CPU_XSAVEC_FLAGS",
265 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
266 { "CPU_PREFETCHWT1_FLAGS",
272 { "CPU_CLZERO_FLAGS",
274 { "CPU_MWAITX_FLAGS",
277 "CPU_XSAVE_FLAGS|CpuOSPKE" },
280 { "CPU_PTWRITE_FLAGS",
290 { "CPU_VPCLMULQDQ_FLAGS",
292 { "CPU_WBNOINVD_FLAGS",
294 { "CPU_PCONFIG_FLAGS",
296 { "CPU_WAITPKG_FLAGS",
298 { "CPU_CLDEMOTE_FLAGS",
300 { "CPU_AMX_INT8_FLAGS",
302 { "CPU_AMX_BF16_FLAGS",
304 { "CPU_AMX_TILE_FLAGS",
306 { "CPU_MOVDIRI_FLAGS",
308 { "CPU_MOVDIR64B_FLAGS",
310 { "CPU_ENQCMD_FLAGS",
312 { "CPU_SERIALIZE_FLAGS",
314 { "CPU_AVX512_VP2INTERSECT_FLAGS",
315 "CpuAVX512_VP2INTERSECT" },
320 { "CPU_MCOMMIT_FLAGS",
322 { "CPU_SEV_ES_FLAGS",
324 { "CPU_TSXLDTRK_FLAGS",
328 { "CPU_WIDEKL_FLAGS",
330 { "CPU_ANY_X87_FLAGS",
331 "CPU_ANY_287_FLAGS|Cpu8087" },
332 { "CPU_ANY_287_FLAGS",
333 "CPU_ANY_387_FLAGS|Cpu287" },
334 { "CPU_ANY_387_FLAGS",
335 "CPU_ANY_687_FLAGS|Cpu387" },
336 { "CPU_ANY_687_FLAGS",
337 "Cpu687|CpuFISTTP" },
338 { "CPU_ANY_CMOV_FLAGS",
340 { "CPU_ANY_FXSR_FLAGS",
342 { "CPU_ANY_MMX_FLAGS",
343 "CPU_3DNOWA_FLAGS" },
344 { "CPU_ANY_SSE_FLAGS",
345 "CPU_ANY_SSE2_FLAGS|CpuSSE" },
346 { "CPU_ANY_SSE2_FLAGS",
347 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
348 { "CPU_ANY_SSE3_FLAGS",
349 "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
350 { "CPU_ANY_SSSE3_FLAGS",
351 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
352 { "CPU_ANY_SSE4_1_FLAGS",
353 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
354 { "CPU_ANY_SSE4_2_FLAGS",
356 { "CPU_ANY_SSE4A_FLAGS",
358 { "CPU_ANY_AVX_FLAGS",
359 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
360 { "CPU_ANY_AVX2_FLAGS",
361 "CPU_ANY_AVX512F_FLAGS|CpuAVX2" },
362 { "CPU_ANY_AVX512F_FLAGS",
363 "CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_BF16|CpuAVX512_VP2INTERSECT" },
364 { "CPU_ANY_AVX512CD_FLAGS",
366 { "CPU_ANY_AVX512ER_FLAGS",
368 { "CPU_ANY_AVX512PF_FLAGS",
370 { "CPU_ANY_AVX512DQ_FLAGS",
372 { "CPU_ANY_AVX512BW_FLAGS",
374 { "CPU_ANY_AVX512VL_FLAGS",
376 { "CPU_ANY_AVX512IFMA_FLAGS",
378 { "CPU_ANY_AVX512VBMI_FLAGS",
380 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
381 "CpuAVX512_4FMAPS" },
382 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
383 "CpuAVX512_4VNNIW" },
384 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
385 "CpuAVX512_VPOPCNTDQ" },
386 { "CPU_ANY_IBT_FLAGS",
388 { "CPU_ANY_SHSTK_FLAGS",
390 { "CPU_ANY_AVX512_VBMI2_FLAGS",
392 { "CPU_ANY_AVX512_VNNI_FLAGS",
394 { "CPU_ANY_AVX512_BITALG_FLAGS",
395 "CpuAVX512_BITALG" },
396 { "CPU_ANY_AVX512_BF16_FLAGS",
398 { "CPU_ANY_AMX_INT8_FLAGS",
400 { "CPU_ANY_AMX_BF16_FLAGS",
402 { "CPU_ANY_AMX_TILE_FLAGS",
403 "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16" },
404 { "CPU_ANY_MOVDIRI_FLAGS",
406 { "CPU_ANY_MOVDIR64B_FLAGS",
408 { "CPU_ANY_ENQCMD_FLAGS",
410 { "CPU_ANY_SERIALIZE_FLAGS",
412 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
413 "CpuAVX512_VP2INTERSECT" },
414 { "CPU_ANY_TDX_FLAGS",
416 { "CPU_ANY_TSXLDTRK_FLAGS",
418 { "CPU_ANY_KL_FLAGS",
420 { "CPU_ANY_WIDEKL_FLAGS",
424 static initializer operand_type_init
[] =
426 { "OPERAND_TYPE_NONE",
428 { "OPERAND_TYPE_REG8",
430 { "OPERAND_TYPE_REG16",
432 { "OPERAND_TYPE_REG32",
434 { "OPERAND_TYPE_REG64",
436 { "OPERAND_TYPE_IMM1",
438 { "OPERAND_TYPE_IMM8",
440 { "OPERAND_TYPE_IMM8S",
442 { "OPERAND_TYPE_IMM16",
444 { "OPERAND_TYPE_IMM32",
446 { "OPERAND_TYPE_IMM32S",
448 { "OPERAND_TYPE_IMM64",
450 { "OPERAND_TYPE_BASEINDEX",
452 { "OPERAND_TYPE_DISP8",
454 { "OPERAND_TYPE_DISP16",
456 { "OPERAND_TYPE_DISP32",
458 { "OPERAND_TYPE_DISP32S",
460 { "OPERAND_TYPE_DISP64",
462 { "OPERAND_TYPE_INOUTPORTREG",
463 "Instance=RegD|Word" },
464 { "OPERAND_TYPE_SHIFTCOUNT",
465 "Instance=RegC|Byte" },
466 { "OPERAND_TYPE_CONTROL",
468 { "OPERAND_TYPE_TEST",
470 { "OPERAND_TYPE_DEBUG",
472 { "OPERAND_TYPE_FLOATREG",
474 { "OPERAND_TYPE_FLOATACC",
475 "Instance=Accum|Tbyte" },
476 { "OPERAND_TYPE_SREG",
478 { "OPERAND_TYPE_REGMMX",
480 { "OPERAND_TYPE_REGXMM",
481 "Class=RegSIMD|Xmmword" },
482 { "OPERAND_TYPE_REGYMM",
483 "Class=RegSIMD|Ymmword" },
484 { "OPERAND_TYPE_REGZMM",
485 "Class=RegSIMD|Zmmword" },
486 { "OPERAND_TYPE_REGTMM",
487 "Class=RegSIMD|Tmmword" },
488 { "OPERAND_TYPE_REGMASK",
490 { "OPERAND_TYPE_REGBND",
492 { "OPERAND_TYPE_ACC8",
493 "Instance=Accum|Byte" },
494 { "OPERAND_TYPE_ACC16",
495 "Instance=Accum|Word" },
496 { "OPERAND_TYPE_ACC32",
497 "Instance=Accum|Dword" },
498 { "OPERAND_TYPE_ACC64",
499 "Instance=Accum|Qword" },
500 { "OPERAND_TYPE_DISP16_32",
502 { "OPERAND_TYPE_ANYDISP",
503 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
504 { "OPERAND_TYPE_IMM16_32",
506 { "OPERAND_TYPE_IMM16_32S",
508 { "OPERAND_TYPE_IMM16_32_32S",
509 "Imm16|Imm32|Imm32S" },
510 { "OPERAND_TYPE_IMM32_64",
512 { "OPERAND_TYPE_IMM32_32S_DISP32",
513 "Imm32|Imm32S|Disp32" },
514 { "OPERAND_TYPE_IMM64_DISP64",
516 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
517 "Imm32|Imm32S|Imm64|Disp32" },
518 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
519 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
520 { "OPERAND_TYPE_ANYIMM",
521 "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
524 typedef struct bitfield
531 #define BITFIELD(n) { n, 0, #n }
533 static bitfield cpu_flags
[] =
543 BITFIELD (CpuClflush
),
545 BITFIELD (CpuSYSCALL
),
550 BITFIELD (CpuFISTTP
),
556 BITFIELD (CpuSSE4_1
),
557 BITFIELD (CpuSSE4_2
),
560 BITFIELD (CpuAVX512F
),
561 BITFIELD (CpuAVX512CD
),
562 BITFIELD (CpuAVX512ER
),
563 BITFIELD (CpuAVX512PF
),
564 BITFIELD (CpuAVX512VL
),
565 BITFIELD (CpuAVX512DQ
),
566 BITFIELD (CpuAVX512BW
),
572 BITFIELD (Cpu3dnowA
),
573 BITFIELD (CpuPadLock
),
578 BITFIELD (CpuXsaveopt
),
580 BITFIELD (CpuPCLMUL
),
591 BITFIELD (CpuRdtscp
),
592 BITFIELD (CpuFSGSBase
),
597 BITFIELD (CpuPOPCNT
),
600 BITFIELD (CpuINVPCID
),
601 BITFIELD (CpuVMFUNC
),
602 BITFIELD (CpuRDSEED
),
604 BITFIELD (CpuPRFCHW
),
607 BITFIELD (CpuClflushOpt
),
608 BITFIELD (CpuXSAVES
),
609 BITFIELD (CpuXSAVEC
),
610 BITFIELD (CpuPREFETCHWT1
),
616 BITFIELD (CpuAVX512IFMA
),
617 BITFIELD (CpuAVX512VBMI
),
618 BITFIELD (CpuAVX512_4FMAPS
),
619 BITFIELD (CpuAVX512_4VNNIW
),
620 BITFIELD (CpuAVX512_VPOPCNTDQ
),
621 BITFIELD (CpuAVX512_VBMI2
),
622 BITFIELD (CpuAVX512_VNNI
),
623 BITFIELD (CpuAVX512_BITALG
),
624 BITFIELD (CpuAVX512_BF16
),
625 BITFIELD (CpuAVX512_VP2INTERSECT
),
627 BITFIELD (CpuMWAITX
),
628 BITFIELD (CpuCLZERO
),
631 BITFIELD (CpuPTWRITE
),
636 BITFIELD (CpuVPCLMULQDQ
),
637 BITFIELD (CpuWBNOINVD
),
638 BITFIELD (CpuPCONFIG
),
639 BITFIELD (CpuWAITPKG
),
640 BITFIELD (CpuCLDEMOTE
),
641 BITFIELD (CpuAMX_INT8
),
642 BITFIELD (CpuAMX_BF16
),
643 BITFIELD (CpuAMX_TILE
),
644 BITFIELD (CpuMOVDIRI
),
645 BITFIELD (CpuMOVDIR64B
),
646 BITFIELD (CpuENQCMD
),
647 BITFIELD (CpuSERIALIZE
),
649 BITFIELD (CpuMCOMMIT
),
650 BITFIELD (CpuSEV_ES
),
651 BITFIELD (CpuTSXLDTRK
),
653 BITFIELD (CpuWideKL
),
655 BITFIELD (CpuUnused
),
659 static bitfield opcode_modifiers
[] =
669 BITFIELD (CheckRegSize
),
670 BITFIELD (MnemonicSize
),
681 BITFIELD (BNDPrefixOk
),
682 BITFIELD (NoTrackPrefixOk
),
683 BITFIELD (IsLockable
),
684 BITFIELD (RegKludge
),
685 BITFIELD (Implicit1stXmm0
),
686 BITFIELD (RepPrefixOk
),
687 BITFIELD (HLEPrefixOk
),
690 BITFIELD (AddrPrefixOpReg
),
698 BITFIELD (OpcodePrefix
),
699 BITFIELD (VexSources
),
705 BITFIELD (Broadcast
),
706 BITFIELD (StaticRounding
),
708 BITFIELD (Disp8MemShift
),
709 BITFIELD (NoDefMask
),
710 BITFIELD (ImplicitQuadGroup
),
711 BITFIELD (SwapSources
),
713 BITFIELD (ATTMnemonic
),
714 BITFIELD (ATTSyntax
),
715 BITFIELD (IntelSyntax
),
719 #define CLASS(n) #n, n
721 static const struct {
723 enum operand_class value
;
724 } operand_classes
[] = {
738 #define INSTANCE(n) #n, n
740 static const struct {
742 enum operand_instance value
;
743 } operand_instances
[] = {
752 static bitfield operand_types
[] =
761 BITFIELD (BaseIndex
),
777 BITFIELD (Unspecified
),
783 static const char *filename
;
784 static i386_cpu_flags active_cpu_flags
;
785 static int active_isstring
;
787 struct template_arg
{
788 const struct template_arg
*next
;
792 struct template_instance
{
793 const struct template_instance
*next
;
795 const struct template_arg
*args
;
798 struct template_param
{
799 const struct template_param
*next
;
804 const struct template *next
;
806 const struct template_instance
*instances
;
807 const struct template_param
*params
;
810 static const struct template *templates
;
813 compare (const void *x
, const void *y
)
815 const bitfield
*xp
= (const bitfield
*) x
;
816 const bitfield
*yp
= (const bitfield
*) y
;
817 return xp
->position
- yp
->position
;
821 fail (const char *message
, ...)
825 va_start (args
, message
);
826 fprintf (stderr
, _("%s: error: "), program_name
);
827 vfprintf (stderr
, message
, args
);
833 process_copyright (FILE *fp
)
835 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
836 /* Copyright (C) 2007-2020 Free Software Foundation, Inc.\n\
838 This file is part of the GNU opcodes library.\n\
840 This library is free software; you can redistribute it and/or modify\n\
841 it under the terms of the GNU General Public License as published by\n\
842 the Free Software Foundation; either version 3, or (at your option)\n\
843 any later version.\n\
845 It is distributed in the hope that it will be useful, but WITHOUT\n\
846 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
847 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
848 License for more details.\n\
850 You should have received a copy of the GNU General Public License\n\
851 along with this program; if not, write to the Free Software\n\
852 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
853 MA 02110-1301, USA. */\n");
856 /* Remove leading white spaces. */
859 remove_leading_whitespaces (char *str
)
861 while (ISSPACE (*str
))
866 /* Remove trailing white spaces. */
869 remove_trailing_whitespaces (char *str
)
871 size_t last
= strlen (str
);
879 if (ISSPACE (str
[last
]))
887 /* Find next field separated by SEP and terminate it. Return a
888 pointer to the one after it. */
891 next_field (char *str
, char sep
, char **next
, char *last
)
895 p
= remove_leading_whitespaces (str
);
896 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
899 remove_trailing_whitespaces (p
);
909 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
912 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
915 char *str
, *next
, *last
;
918 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
919 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
921 /* Turn on selective bits. */
922 char *init
= xstrdup (cpu_flag_init
[i
].init
);
923 last
= init
+ strlen (init
);
924 for (next
= init
; next
&& next
< last
; )
926 str
= next_field (next
, '|', &next
, last
);
928 set_bitfield (str
, array
, 1, size
, lineno
);
938 set_bitfield (char *f
, bitfield
*array
, int value
,
939 unsigned int size
, int lineno
)
943 /* Ignore empty fields; they may result from template expansions. */
947 if (strcmp (f
, "CpuFP") == 0)
949 set_bitfield("Cpu387", array
, value
, size
, lineno
);
950 set_bitfield("Cpu287", array
, value
, size
, lineno
);
953 else if (strcmp (f
, "Mmword") == 0)
955 else if (strcmp (f
, "Oword") == 0)
958 for (i
= 0; i
< size
; i
++)
959 if (strcasecmp (array
[i
].name
, f
) == 0)
961 array
[i
].value
= value
;
967 const char *v
= strchr (f
, '=');
974 for (i
= 0; i
< size
; i
++)
975 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
977 value
= strtol (v
+ 1, &end
, 0);
980 array
[i
].value
= value
;
988 /* Handle CPU_XXX_FLAGS. */
989 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
993 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
995 fail (_("unknown bitfield: %s\n"), f
);
999 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
1000 int macro
, const char *comma
, const char *indent
)
1004 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
1006 fprintf (table
, "%s{ { ", indent
);
1008 for (i
= 0; i
< size
- 1; i
++)
1010 if (((i
+ 1) % 20) != 0)
1011 fprintf (table
, "%d, ", flags
[i
].value
);
1013 fprintf (table
, "%d,", flags
[i
].value
);
1014 if (((i
+ 1) % 20) == 0)
1016 /* We need \\ for macro. */
1018 fprintf (table
, " \\\n %s", indent
);
1020 fprintf (table
, "\n %s", indent
);
1023 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
1026 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
1030 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
1031 const char *comma
, const char *indent
,
1034 char *str
, *next
, *last
;
1036 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
1038 /* Copy the default cpu flags. */
1039 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
1041 if (strcasecmp (flag
, "unknown") == 0)
1043 /* We turn on everything except for cpu64 in case of
1044 CPU_UNKNOWN_FLAGS. */
1045 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1046 if (flags
[i
].position
!= Cpu64
)
1049 else if (flag
[0] == '~')
1051 last
= flag
+ strlen (flag
);
1058 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
1065 /* First we turn on everything except for cpu64. */
1066 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1067 if (flags
[i
].position
!= Cpu64
)
1070 /* Turn off selective bits. */
1071 for (; next
&& next
< last
; )
1073 str
= next_field (next
, '|', &next
, last
);
1075 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
1078 else if (strcmp (flag
, "0"))
1080 /* Turn on selective bits. */
1081 last
= flag
+ strlen (flag
);
1082 for (next
= flag
; next
&& next
< last
; )
1084 str
= next_field (next
, '|', &next
, last
);
1086 set_bitfield (str
, flags
, 1, 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
, char **opnd
, int lineno
)
1167 char *str
, *next
, *last
;
1168 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1169 unsigned int regular_encoding
= 1;
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)
1189 val
= adjust_broadcast_modifier (opnd
);
1190 regular_encoding
= 0;
1192 else if (strcasecmp(str
, "Vex") == 0
1193 || strncasecmp(str
, "Vex=", 4) == 0
1194 || strcasecmp(str
, "EVex") == 0
1195 || strncasecmp(str
, "EVex=", 5) == 0
1196 || strncasecmp(str
, "Disp8MemShift=", 14) == 0
1197 || strncasecmp(str
, "Masking=", 8) == 0
1198 || strcasecmp(str
, "SAE") == 0
1199 || strcasecmp(str
, "IsPrefix") == 0)
1200 regular_encoding
= 0;
1202 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1204 if (strcasecmp(str
, "IsString") == 0)
1205 active_isstring
= 1;
1207 if (strcasecmp(str
, "W") == 0)
1210 if (strcasecmp(str
, "No_bSuf") == 0)
1212 if (strcasecmp(str
, "No_wSuf") == 0)
1214 if (strcasecmp(str
, "No_lSuf") == 0)
1216 if (strcasecmp(str
, "No_qSuf") == 0)
1221 if (have_w
&& !bwlq_suf
)
1222 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1223 if (have_w
&& !(bwlq_suf
& 1))
1224 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1226 if (have_w
&& !(bwlq_suf
& ~1))
1228 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1231 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1233 return regular_encoding
;
1243 output_operand_type (FILE *table
, enum operand_class
class,
1244 enum operand_instance instance
,
1245 const bitfield
*types
, unsigned int size
,
1246 enum stage stage
, const char *indent
)
1250 fprintf (table
, "{ { %d, %d, ", class, instance
);
1252 for (i
= 0; i
< size
- 1; i
++)
1254 if (((i
+ 3) % 20) != 0)
1255 fprintf (table
, "%d, ", types
[i
].value
);
1257 fprintf (table
, "%d,", types
[i
].value
);
1258 if (((i
+ 3) % 20) == 0)
1260 /* We need \\ for macro. */
1261 if (stage
== stage_macros
)
1262 fprintf (table
, " \\\n%s", indent
);
1264 fprintf (table
, "\n%s", indent
);
1268 fprintf (table
, "%d } }", types
[i
].value
);
1272 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1273 const char *indent
, int lineno
)
1275 char *str
, *next
, *last
;
1276 enum operand_class
class = ClassNone
;
1277 enum operand_instance instance
= InstanceNone
;
1278 bitfield types
[ARRAY_SIZE (operand_types
)];
1280 /* Copy the default operand type. */
1281 memcpy (types
, operand_types
, sizeof (types
));
1283 if (strcmp (op
, "0"))
1287 last
= op
+ strlen (op
);
1288 for (next
= op
; next
&& next
< last
; )
1290 str
= next_field (next
, '|', &next
, last
);
1295 if (!strncmp(str
, "Class=", 6))
1297 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1298 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1300 class = operand_classes
[i
].value
;
1306 if (str
&& !strncmp(str
, "Instance=", 9))
1308 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1309 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1311 instance
= operand_instances
[i
].value
;
1319 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1320 if (strcasecmp(str
, "BaseIndex") == 0)
1325 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1327 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1328 if (!active_cpu_flags
.bitfield
.cpu64
1329 && !active_cpu_flags
.bitfield
.cpumpx
)
1330 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1331 if (!active_cpu_flags
.bitfield
.cpu64
)
1332 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1333 if (!active_cpu_flags
.bitfield
.cpuno64
)
1334 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1337 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1342 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1343 char *last
, int lineno
)
1346 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1347 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1349 /* Find number of operands. */
1350 operands
= next_field (str
, ',', &str
, last
);
1352 /* Find base_opcode. */
1353 base_opcode
= next_field (str
, ',', &str
, last
);
1355 /* Find extension_opcode. */
1356 extension_opcode
= next_field (str
, ',', &str
, last
);
1358 /* Find opcode_length. */
1359 opcode_length
= next_field (str
, ',', &str
, last
);
1361 /* Find cpu_flags. */
1362 cpu_flags
= next_field (str
, ',', &str
, last
);
1364 /* Find opcode_modifier. */
1365 opcode_modifier
= next_field (str
, ',', &str
, last
);
1367 /* Remove the first {. */
1368 str
= remove_leading_whitespaces (str
);
1371 str
= remove_leading_whitespaces (str
+ 1);
1375 /* There are at least "X}". */
1379 /* Remove trailing white spaces and }. */
1383 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1392 /* Find operand_types. */
1393 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1397 operand_types
[i
] = NULL
;
1401 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1402 if (*operand_types
[i
] == '0')
1405 operand_types
[i
] = NULL
;
1410 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1411 name
, base_opcode
, extension_opcode
, opcode_length
, operands
);
1413 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1415 if (process_i386_opcode_modifier (table
, opcode_modifier
,
1416 operand_types
, lineno
))
1419 unsigned long int length
= strtoul (opcode_length
, &end
, 0);
1420 unsigned long int opcode
= strtoul (base_opcode
, &end
, 0);
1424 if ((opcode
>> 24) != 0)
1425 fail (_("%s: %s: (base_opcode >> 24) != 0: %s\n"),
1426 filename
, name
, base_opcode
);
1429 if ((opcode
>> 16) != 0)
1430 fail (_("%s: %s: (base_opcode >> 16) != 0: %s\n"),
1431 filename
, name
, base_opcode
);
1434 if ((opcode
>> 8) != 0)
1435 fail (_("%s: %s: (base_opcode >> 8) != 0: %s\n"),
1436 filename
, name
, base_opcode
);
1440 fail (_("%s: %s: base_opcode != 0: %s\n"),
1441 filename
, name
, base_opcode
);
1444 fail (_("%s: %s: invalid opcode length: %s\n"),
1445 filename
, name
, opcode_length
);
1450 fprintf (table
, " { ");
1452 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1454 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1457 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1463 fprintf (table
, ",\n ");
1465 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1468 fprintf (table
, " } },\n");
1471 struct opcode_hash_entry
1473 struct opcode_hash_entry
*next
;
1479 /* Calculate the hash value of an opcode hash entry P. */
1482 opcode_hash_hash (const void *p
)
1484 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1485 return htab_hash_string (entry
->name
);
1488 /* Compare a string Q against an opcode hash entry P. */
1491 opcode_hash_eq (const void *p
, const void *q
)
1493 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1494 const char *name
= (const char *) q
;
1495 return strcmp (name
, entry
->name
) == 0;
1499 parse_template (char *buf
, int lineno
)
1501 char sep
, *end
, *name
;
1502 struct template *tmpl
= xmalloc (sizeof (*tmpl
));
1503 struct template_instance
*last_inst
= NULL
;
1505 buf
= remove_leading_whitespaces (buf
+ 1);
1506 end
= strchr (buf
, ':');
1508 fail ("%s: %d: missing ':'\n", filename
, lineno
);
1510 remove_trailing_whitespaces (buf
);
1513 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1514 tmpl
->name
= xstrdup (buf
);
1516 tmpl
->params
= NULL
;
1518 struct template_param
*param
;
1520 buf
= remove_leading_whitespaces (end
);
1521 end
= strpbrk (buf
, ":,");
1523 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1527 remove_trailing_whitespaces (buf
);
1529 param
= xmalloc (sizeof (*param
));
1530 param
->name
= xstrdup (buf
);
1531 param
->next
= tmpl
->params
;
1532 tmpl
->params
= param
;
1533 } while (sep
== ':');
1535 tmpl
->instances
= NULL
;
1537 struct template_instance
*inst
;
1539 const struct template_param
*param
;
1541 buf
= remove_leading_whitespaces (end
);
1542 end
= strpbrk (buf
, ",>");
1544 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1549 inst
= xmalloc (sizeof (*inst
));
1551 cur
= next_field (buf
, ':', &next
, end
);
1552 inst
->name
= xstrdup (cur
);
1554 for (param
= tmpl
->params
; param
; param
= param
->next
)
1556 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1558 cur
= next_field (next
, ':', &next
, end
);
1560 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1561 arg
->val
= xstrdup (cur
);
1562 arg
->next
= inst
->args
;
1566 if (tmpl
->instances
)
1567 last_inst
->next
= inst
;
1569 tmpl
->instances
= inst
;
1571 } while (sep
== ',');
1573 buf
= remove_leading_whitespaces (end
);
1575 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1576 filename
, lineno
, buf
);
1578 tmpl
->next
= templates
;
1583 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1584 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1586 static unsigned int idx
, opcode_array_size
;
1587 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1588 struct opcode_hash_entry
**hash_slot
, **entry
;
1589 char *ptr1
= strchr(name
, '<'), *ptr2
;
1593 /* Get the slot in hash table. */
1594 hash_slot
= (struct opcode_hash_entry
**)
1595 htab_find_slot_with_hash (opcode_hash_table
, name
,
1596 htab_hash_string (name
),
1599 if (*hash_slot
== NULL
)
1601 /* It is the new one. Put it on opcode array. */
1602 if (idx
>= opcode_array_size
)
1604 /* Grow the opcode array when needed. */
1605 opcode_array_size
+= 1024;
1606 opcode_array
= (struct opcode_hash_entry
**)
1607 xrealloc (opcode_array
,
1608 sizeof (*opcode_array
) * opcode_array_size
);
1609 *opcode_array_p
= opcode_array
;
1612 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1613 xmalloc (sizeof (struct opcode_hash_entry
));
1614 opcode_array
[idx
]->next
= NULL
;
1615 opcode_array
[idx
]->name
= xstrdup (name
);
1616 opcode_array
[idx
]->opcode
= xstrdup (str
);
1617 opcode_array
[idx
]->lineno
= lineno
;
1618 *hash_slot
= opcode_array
[idx
];
1623 /* Append it to the existing one. */
1625 while ((*entry
) != NULL
)
1626 entry
= &(*entry
)->next
;
1627 *entry
= (struct opcode_hash_entry
*)
1628 xmalloc (sizeof (struct opcode_hash_entry
));
1629 (*entry
)->next
= NULL
;
1630 (*entry
)->name
= (*hash_slot
)->name
;
1631 (*entry
)->opcode
= xstrdup (str
);
1632 (*entry
)->lineno
= lineno
;
1635 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1636 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1639 const struct template *tmpl
;
1640 const struct template_instance
*inst
;
1643 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1644 remove_trailing_whitespaces (ptr1
);
1648 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1649 if (!strcmp(ptr1
, tmpl
->name
))
1652 fail ("reference to unknown template '%s'\n", ptr1
);
1654 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1656 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1657 char *str2
= xmalloc(2 * strlen(str
));
1660 strcpy (name2
, name
);
1661 strcat (name2
, inst
->name
);
1662 strcat (name2
, ptr2
);
1664 for (ptr1
= str2
, src
= str
; *src
; )
1666 const char *ident
= tmpl
->name
, *end
;
1667 const struct template_param
*param
;
1668 const struct template_arg
*arg
;
1670 if ((*ptr1
= *src
++) != '<')
1675 while (ISSPACE(*src
))
1677 while (*ident
&& *src
== *ident
)
1679 while (ISSPACE(*src
))
1681 if (*src
!= ':' || *ident
!= '\0')
1683 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1684 ptr1
+= ident
- tmpl
->name
;
1687 while (ISSPACE(*++src
))
1691 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1694 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1695 param
= param
->next
, arg
= arg
->next
)
1697 if (end
- src
== strlen (param
->name
)
1698 && !memcmp (src
, param
->name
, end
- src
))
1706 fail ("template '%s' has no parameter '%.*s'\n",
1707 tmpl
->name
, (int)(end
- src
), src
);
1709 while (ISSPACE(*src
))
1712 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1714 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1715 ptr1
+= strlen(arg
->val
);
1721 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1733 process_i386_opcodes (FILE *table
)
1738 char *str
, *p
, *last
, *name
;
1739 htab_t opcode_hash_table
;
1740 struct opcode_hash_entry
**opcode_array
= NULL
;
1741 int lineno
= 0, marker
= 0;
1743 filename
= "i386-opc.tbl";
1747 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1748 opcode_hash_eq
, NULL
,
1751 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1752 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1754 /* Put everything on opcode array. */
1757 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1762 p
= remove_leading_whitespaces (buf
);
1764 /* Skip comments. */
1765 str
= strstr (p
, "//");
1769 /* Remove trailing white spaces. */
1770 remove_trailing_whitespaces (p
);
1775 if (!strcmp("### MARKER ###", buf
))
1779 /* Since we ignore all included files (we only care about their
1780 #define-s here), we don't need to monitor filenames. The final
1781 line number directive is going to refer to the main source file
1786 p
= remove_leading_whitespaces (p
+ 1);
1787 if (!strncmp(p
, "line", 4))
1789 ln
= strtoul (p
, &end
, 10);
1790 if (ln
> 1 && ln
< INT_MAX
1791 && *remove_leading_whitespaces (end
) == '"')
1794 /* Ignore comments. */
1799 parse_template (p
, lineno
);
1807 last
= p
+ strlen (p
);
1810 name
= next_field (p
, ',', &str
, last
);
1812 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1816 /* Process opcode array. */
1817 for (j
= 0; j
< i
; j
++)
1819 struct opcode_hash_entry
*next
;
1821 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1825 lineno
= next
->lineno
;
1826 last
= str
+ strlen (str
);
1827 output_i386_opcode (table
, name
, str
, last
, lineno
);
1833 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1835 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1837 process_i386_opcode_modifier (table
, "0", NULL
, -1);
1839 fprintf (table
, " { ");
1840 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1841 fprintf (table
, " } }\n");
1843 fprintf (table
, "};\n");
1847 process_i386_registers (FILE *table
)
1851 char *str
, *p
, *last
;
1852 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1853 char *dw2_32_num
, *dw2_64_num
;
1856 filename
= "i386-reg.tbl";
1857 fp
= fopen (filename
, "r");
1859 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1862 fprintf (table
, "\n/* i386 register table. */\n\n");
1863 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1867 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1872 p
= remove_leading_whitespaces (buf
);
1874 /* Skip comments. */
1875 str
= strstr (p
, "//");
1879 /* Remove trailing white spaces. */
1880 remove_trailing_whitespaces (p
);
1885 fprintf (table
, "%s\n", p
);
1893 last
= p
+ strlen (p
);
1895 /* Find reg_name. */
1896 reg_name
= next_field (p
, ',', &str
, last
);
1898 /* Find reg_type. */
1899 reg_type
= next_field (str
, ',', &str
, last
);
1901 /* Find reg_flags. */
1902 reg_flags
= next_field (str
, ',', &str
, last
);
1905 reg_num
= next_field (str
, ',', &str
, last
);
1907 fprintf (table
, " { \"%s\",\n ", reg_name
);
1909 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1912 /* Find 32-bit Dwarf2 register number. */
1913 dw2_32_num
= next_field (str
, ',', &str
, last
);
1915 /* Find 64-bit Dwarf2 register number. */
1916 dw2_64_num
= next_field (str
, ',', &str
, last
);
1918 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1919 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1924 fprintf (table
, "};\n");
1926 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1930 process_i386_initializers (void)
1933 FILE *fp
= fopen ("i386-init.h", "w");
1937 fail (_("can't create i386-init.h, errno = %s\n"),
1940 process_copyright (fp
);
1942 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1944 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1945 init
= xstrdup (cpu_flag_init
[i
].init
);
1946 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1950 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1952 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1953 init
= xstrdup (operand_type_init
[i
].init
);
1954 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1962 /* Program options. */
1963 #define OPTION_SRCDIR 200
1965 struct option long_options
[] =
1967 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1968 {"debug", no_argument
, NULL
, 'd'},
1969 {"version", no_argument
, NULL
, 'V'},
1970 {"help", no_argument
, NULL
, 'h'},
1971 {0, no_argument
, NULL
, 0}
1975 print_version (void)
1977 printf ("%s: version 1.0\n", program_name
);
1982 usage (FILE * stream
, int status
)
1984 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1990 main (int argc
, char **argv
)
1992 extern int chdir (char *);
1993 char *srcdir
= NULL
;
1995 unsigned int i
, cpumax
;
1998 program_name
= *argv
;
1999 xmalloc_set_program_name (program_name
);
2001 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2026 if (chdir (srcdir
) != 0)
2027 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2028 srcdir
, xstrerror (errno
));
2030 /* cpu_flags isn't sorted by position. */
2032 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2033 if (cpu_flags
[i
].position
> cpumax
)
2034 cpumax
= cpu_flags
[i
].position
;
2036 /* Check the unused bitfield in i386_cpu_flags. */
2038 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2040 if ((cpumax
- 1) != CpuMax
)
2041 fail (_("CpuMax != %d!\n"), cpumax
);
2043 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2045 if (cpumax
!= CpuMax
)
2046 fail (_("CpuMax != %d!\n"), cpumax
);
2048 c
= CpuNumOfBits
- CpuMax
- 1;
2050 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2053 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2055 /* Check the unused bitfield in i386_operand_type. */
2057 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2060 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2063 c
= OTNumOfBits
- OTNum
;
2065 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2068 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2071 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2072 sizeof (opcode_modifiers
[0]), compare
);
2074 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2075 sizeof (operand_types
[0]), compare
);
2077 table
= fopen ("i386-tbl.h", "w");
2079 fail (_("can't create i386-tbl.h, errno = %s\n"),
2082 process_copyright (table
);
2084 process_i386_opcodes (table
);
2085 process_i386_registers (table
);
2086 process_i386_initializers ();