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" },
318 { "CPU_MCOMMIT_FLAGS",
320 { "CPU_SEV_ES_FLAGS",
322 { "CPU_TSXLDTRK_FLAGS",
326 { "CPU_WIDEKL_FLAGS",
328 { "CPU_ANY_X87_FLAGS",
329 "CPU_ANY_287_FLAGS|Cpu8087" },
330 { "CPU_ANY_287_FLAGS",
331 "CPU_ANY_387_FLAGS|Cpu287" },
332 { "CPU_ANY_387_FLAGS",
333 "CPU_ANY_687_FLAGS|Cpu387" },
334 { "CPU_ANY_687_FLAGS",
335 "Cpu687|CpuFISTTP" },
336 { "CPU_ANY_CMOV_FLAGS",
338 { "CPU_ANY_FXSR_FLAGS",
340 { "CPU_ANY_MMX_FLAGS",
341 "CPU_3DNOWA_FLAGS" },
342 { "CPU_ANY_SSE_FLAGS",
343 "CPU_ANY_SSE2_FLAGS|CpuSSE" },
344 { "CPU_ANY_SSE2_FLAGS",
345 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
346 { "CPU_ANY_SSE3_FLAGS",
347 "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
348 { "CPU_ANY_SSSE3_FLAGS",
349 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
350 { "CPU_ANY_SSE4_1_FLAGS",
351 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
352 { "CPU_ANY_SSE4_2_FLAGS",
354 { "CPU_ANY_SSE4A_FLAGS",
356 { "CPU_ANY_AVX_FLAGS",
357 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
358 { "CPU_ANY_AVX2_FLAGS",
359 "CPU_ANY_AVX512F_FLAGS|CpuAVX2" },
360 { "CPU_ANY_AVX512F_FLAGS",
361 "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" },
362 { "CPU_ANY_AVX512CD_FLAGS",
364 { "CPU_ANY_AVX512ER_FLAGS",
366 { "CPU_ANY_AVX512PF_FLAGS",
368 { "CPU_ANY_AVX512DQ_FLAGS",
370 { "CPU_ANY_AVX512BW_FLAGS",
372 { "CPU_ANY_AVX512VL_FLAGS",
374 { "CPU_ANY_AVX512IFMA_FLAGS",
376 { "CPU_ANY_AVX512VBMI_FLAGS",
378 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
379 "CpuAVX512_4FMAPS" },
380 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
381 "CpuAVX512_4VNNIW" },
382 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
383 "CpuAVX512_VPOPCNTDQ" },
384 { "CPU_ANY_IBT_FLAGS",
386 { "CPU_ANY_SHSTK_FLAGS",
388 { "CPU_ANY_AVX512_VBMI2_FLAGS",
390 { "CPU_ANY_AVX512_VNNI_FLAGS",
392 { "CPU_ANY_AVX512_BITALG_FLAGS",
393 "CpuAVX512_BITALG" },
394 { "CPU_ANY_AVX512_BF16_FLAGS",
396 { "CPU_ANY_AMX_INT8_FLAGS",
398 { "CPU_ANY_AMX_BF16_FLAGS",
400 { "CPU_ANY_AMX_TILE_FLAGS",
401 "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16" },
402 { "CPU_ANY_MOVDIRI_FLAGS",
404 { "CPU_ANY_MOVDIR64B_FLAGS",
406 { "CPU_ANY_ENQCMD_FLAGS",
408 { "CPU_ANY_SERIALIZE_FLAGS",
410 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
411 "CpuAVX512_VP2INTERSECT" },
412 { "CPU_ANY_TSXLDTRK_FLAGS",
414 { "CPU_ANY_KL_FLAGS",
416 { "CPU_ANY_WIDEKL_FLAGS",
420 static initializer operand_type_init
[] =
422 { "OPERAND_TYPE_NONE",
424 { "OPERAND_TYPE_REG8",
426 { "OPERAND_TYPE_REG16",
428 { "OPERAND_TYPE_REG32",
430 { "OPERAND_TYPE_REG64",
432 { "OPERAND_TYPE_IMM1",
434 { "OPERAND_TYPE_IMM8",
436 { "OPERAND_TYPE_IMM8S",
438 { "OPERAND_TYPE_IMM16",
440 { "OPERAND_TYPE_IMM32",
442 { "OPERAND_TYPE_IMM32S",
444 { "OPERAND_TYPE_IMM64",
446 { "OPERAND_TYPE_BASEINDEX",
448 { "OPERAND_TYPE_DISP8",
450 { "OPERAND_TYPE_DISP16",
452 { "OPERAND_TYPE_DISP32",
454 { "OPERAND_TYPE_DISP32S",
456 { "OPERAND_TYPE_DISP64",
458 { "OPERAND_TYPE_INOUTPORTREG",
459 "Instance=RegD|Word" },
460 { "OPERAND_TYPE_SHIFTCOUNT",
461 "Instance=RegC|Byte" },
462 { "OPERAND_TYPE_CONTROL",
464 { "OPERAND_TYPE_TEST",
466 { "OPERAND_TYPE_DEBUG",
468 { "OPERAND_TYPE_FLOATREG",
470 { "OPERAND_TYPE_FLOATACC",
471 "Instance=Accum|Tbyte" },
472 { "OPERAND_TYPE_SREG",
474 { "OPERAND_TYPE_REGMMX",
476 { "OPERAND_TYPE_REGXMM",
477 "Class=RegSIMD|Xmmword" },
478 { "OPERAND_TYPE_REGYMM",
479 "Class=RegSIMD|Ymmword" },
480 { "OPERAND_TYPE_REGZMM",
481 "Class=RegSIMD|Zmmword" },
482 { "OPERAND_TYPE_REGTMM",
483 "Class=RegSIMD|Tmmword" },
484 { "OPERAND_TYPE_REGMASK",
486 { "OPERAND_TYPE_REGBND",
488 { "OPERAND_TYPE_ACC8",
489 "Instance=Accum|Byte" },
490 { "OPERAND_TYPE_ACC16",
491 "Instance=Accum|Word" },
492 { "OPERAND_TYPE_ACC32",
493 "Instance=Accum|Dword" },
494 { "OPERAND_TYPE_ACC64",
495 "Instance=Accum|Qword" },
496 { "OPERAND_TYPE_DISP16_32",
498 { "OPERAND_TYPE_ANYDISP",
499 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
500 { "OPERAND_TYPE_IMM16_32",
502 { "OPERAND_TYPE_IMM16_32S",
504 { "OPERAND_TYPE_IMM16_32_32S",
505 "Imm16|Imm32|Imm32S" },
506 { "OPERAND_TYPE_IMM32_64",
508 { "OPERAND_TYPE_IMM32_32S_DISP32",
509 "Imm32|Imm32S|Disp32" },
510 { "OPERAND_TYPE_IMM64_DISP64",
512 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
513 "Imm32|Imm32S|Imm64|Disp32" },
514 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
515 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
516 { "OPERAND_TYPE_ANYIMM",
517 "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
520 typedef struct bitfield
527 #define BITFIELD(n) { n, 0, #n }
529 static bitfield cpu_flags
[] =
539 BITFIELD (CpuClflush
),
541 BITFIELD (CpuSYSCALL
),
546 BITFIELD (CpuFISTTP
),
552 BITFIELD (CpuSSE4_1
),
553 BITFIELD (CpuSSE4_2
),
556 BITFIELD (CpuAVX512F
),
557 BITFIELD (CpuAVX512CD
),
558 BITFIELD (CpuAVX512ER
),
559 BITFIELD (CpuAVX512PF
),
560 BITFIELD (CpuAVX512VL
),
561 BITFIELD (CpuAVX512DQ
),
562 BITFIELD (CpuAVX512BW
),
568 BITFIELD (Cpu3dnowA
),
569 BITFIELD (CpuPadLock
),
574 BITFIELD (CpuXsaveopt
),
576 BITFIELD (CpuPCLMUL
),
587 BITFIELD (CpuRdtscp
),
588 BITFIELD (CpuFSGSBase
),
593 BITFIELD (CpuPOPCNT
),
596 BITFIELD (CpuINVPCID
),
597 BITFIELD (CpuVMFUNC
),
598 BITFIELD (CpuRDSEED
),
600 BITFIELD (CpuPRFCHW
),
603 BITFIELD (CpuClflushOpt
),
604 BITFIELD (CpuXSAVES
),
605 BITFIELD (CpuXSAVEC
),
606 BITFIELD (CpuPREFETCHWT1
),
612 BITFIELD (CpuAVX512IFMA
),
613 BITFIELD (CpuAVX512VBMI
),
614 BITFIELD (CpuAVX512_4FMAPS
),
615 BITFIELD (CpuAVX512_4VNNIW
),
616 BITFIELD (CpuAVX512_VPOPCNTDQ
),
617 BITFIELD (CpuAVX512_VBMI2
),
618 BITFIELD (CpuAVX512_VNNI
),
619 BITFIELD (CpuAVX512_BITALG
),
620 BITFIELD (CpuAVX512_BF16
),
621 BITFIELD (CpuAVX512_VP2INTERSECT
),
622 BITFIELD (CpuMWAITX
),
623 BITFIELD (CpuCLZERO
),
626 BITFIELD (CpuPTWRITE
),
631 BITFIELD (CpuVPCLMULQDQ
),
632 BITFIELD (CpuWBNOINVD
),
633 BITFIELD (CpuPCONFIG
),
634 BITFIELD (CpuWAITPKG
),
635 BITFIELD (CpuCLDEMOTE
),
636 BITFIELD (CpuAMX_INT8
),
637 BITFIELD (CpuAMX_BF16
),
638 BITFIELD (CpuAMX_TILE
),
639 BITFIELD (CpuMOVDIRI
),
640 BITFIELD (CpuMOVDIR64B
),
641 BITFIELD (CpuENQCMD
),
642 BITFIELD (CpuSERIALIZE
),
644 BITFIELD (CpuMCOMMIT
),
645 BITFIELD (CpuSEV_ES
),
646 BITFIELD (CpuTSXLDTRK
),
648 BITFIELD (CpuWideKL
),
650 BITFIELD (CpuUnused
),
654 static bitfield opcode_modifiers
[] =
664 BITFIELD (CheckRegSize
),
665 BITFIELD (MnemonicSize
),
676 BITFIELD (BNDPrefixOk
),
677 BITFIELD (NoTrackPrefixOk
),
678 BITFIELD (IsLockable
),
679 BITFIELD (RegKludge
),
680 BITFIELD (Implicit1stXmm0
),
681 BITFIELD (RepPrefixOk
),
682 BITFIELD (HLEPrefixOk
),
685 BITFIELD (AddrPrefixOpReg
),
693 BITFIELD (VexOpcode
),
694 BITFIELD (VexSources
),
700 BITFIELD (Broadcast
),
701 BITFIELD (StaticRounding
),
703 BITFIELD (Disp8MemShift
),
704 BITFIELD (NoDefMask
),
705 BITFIELD (ImplicitQuadGroup
),
706 BITFIELD (SwapSources
),
708 BITFIELD (ATTMnemonic
),
709 BITFIELD (ATTSyntax
),
710 BITFIELD (IntelSyntax
),
714 #define CLASS(n) #n, n
716 static const struct {
718 enum operand_class value
;
719 } operand_classes
[] = {
733 #define INSTANCE(n) #n, n
735 static const struct {
737 enum operand_instance value
;
738 } operand_instances
[] = {
747 static bitfield operand_types
[] =
756 BITFIELD (BaseIndex
),
772 BITFIELD (Unspecified
),
778 static const char *filename
;
779 static i386_cpu_flags active_cpu_flags
;
780 static int active_isstring
;
782 struct template_arg
{
783 const struct template_arg
*next
;
787 struct template_instance
{
788 const struct template_instance
*next
;
790 const struct template_arg
*args
;
793 struct template_param
{
794 const struct template_param
*next
;
799 const struct template *next
;
801 const struct template_instance
*instances
;
802 const struct template_param
*params
;
805 static const struct template *templates
;
808 compare (const void *x
, const void *y
)
810 const bitfield
*xp
= (const bitfield
*) x
;
811 const bitfield
*yp
= (const bitfield
*) y
;
812 return xp
->position
- yp
->position
;
816 fail (const char *message
, ...)
820 va_start (args
, message
);
821 fprintf (stderr
, _("%s: error: "), program_name
);
822 vfprintf (stderr
, message
, args
);
828 process_copyright (FILE *fp
)
830 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
831 /* Copyright (C) 2007-2020 Free Software Foundation, Inc.\n\
833 This file is part of the GNU opcodes library.\n\
835 This library is free software; you can redistribute it and/or modify\n\
836 it under the terms of the GNU General Public License as published by\n\
837 the Free Software Foundation; either version 3, or (at your option)\n\
838 any later version.\n\
840 It is distributed in the hope that it will be useful, but WITHOUT\n\
841 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
842 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
843 License for more details.\n\
845 You should have received a copy of the GNU General Public License\n\
846 along with this program; if not, write to the Free Software\n\
847 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
848 MA 02110-1301, USA. */\n");
851 /* Remove leading white spaces. */
854 remove_leading_whitespaces (char *str
)
856 while (ISSPACE (*str
))
861 /* Remove trailing white spaces. */
864 remove_trailing_whitespaces (char *str
)
866 size_t last
= strlen (str
);
874 if (ISSPACE (str
[last
]))
882 /* Find next field separated by SEP and terminate it. Return a
883 pointer to the one after it. */
886 next_field (char *str
, char sep
, char **next
, char *last
)
890 p
= remove_leading_whitespaces (str
);
891 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
894 remove_trailing_whitespaces (p
);
904 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
907 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
910 char *str
, *next
, *last
;
913 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
914 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
916 /* Turn on selective bits. */
917 char *init
= xstrdup (cpu_flag_init
[i
].init
);
918 last
= init
+ strlen (init
);
919 for (next
= init
; next
&& next
< last
; )
921 str
= next_field (next
, '|', &next
, last
);
923 set_bitfield (str
, array
, 1, size
, lineno
);
933 set_bitfield (char *f
, bitfield
*array
, int value
,
934 unsigned int size
, int lineno
)
938 /* Ignore empty fields; they may result from template expansions. */
942 if (strcmp (f
, "CpuFP") == 0)
944 set_bitfield("Cpu387", array
, value
, size
, lineno
);
945 set_bitfield("Cpu287", array
, value
, size
, lineno
);
948 else if (strcmp (f
, "Mmword") == 0)
950 else if (strcmp (f
, "Oword") == 0)
953 for (i
= 0; i
< size
; i
++)
954 if (strcasecmp (array
[i
].name
, f
) == 0)
956 array
[i
].value
= value
;
962 const char *v
= strchr (f
, '=');
969 for (i
= 0; i
< size
; i
++)
970 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
972 value
= strtol (v
+ 1, &end
, 0);
975 array
[i
].value
= value
;
983 /* Handle CPU_XXX_FLAGS. */
984 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
988 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
990 fail (_("unknown bitfield: %s\n"), f
);
994 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
995 int macro
, const char *comma
, const char *indent
)
999 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
1001 fprintf (table
, "%s{ { ", indent
);
1003 for (i
= 0; i
< size
- 1; i
++)
1005 if (((i
+ 1) % 20) != 0)
1006 fprintf (table
, "%d, ", flags
[i
].value
);
1008 fprintf (table
, "%d,", flags
[i
].value
);
1009 if (((i
+ 1) % 20) == 0)
1011 /* We need \\ for macro. */
1013 fprintf (table
, " \\\n %s", indent
);
1015 fprintf (table
, "\n %s", indent
);
1018 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
1021 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
1025 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
1026 const char *comma
, const char *indent
,
1029 char *str
, *next
, *last
;
1031 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
1033 /* Copy the default cpu flags. */
1034 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
1036 if (strcasecmp (flag
, "unknown") == 0)
1038 /* We turn on everything except for cpu64 in case of
1039 CPU_UNKNOWN_FLAGS. */
1040 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1041 if (flags
[i
].position
!= Cpu64
)
1044 else if (flag
[0] == '~')
1046 last
= flag
+ strlen (flag
);
1053 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
1060 /* First we turn on everything except for cpu64. */
1061 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1062 if (flags
[i
].position
!= Cpu64
)
1065 /* Turn off selective bits. */
1066 for (; next
&& next
< last
; )
1068 str
= next_field (next
, '|', &next
, last
);
1070 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
1073 else if (strcmp (flag
, "0"))
1075 /* Turn on selective bits. */
1076 last
= flag
+ strlen (flag
);
1077 for (next
= flag
; next
&& next
< last
; )
1079 str
= next_field (next
, '|', &next
, last
);
1081 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
1085 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1090 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1094 fprintf (table
, " { ");
1096 for (i
= 0; i
< size
- 1; i
++)
1098 if (((i
+ 1) % 20) != 0)
1099 fprintf (table
, "%d, ", modifier
[i
].value
);
1101 fprintf (table
, "%d,", modifier
[i
].value
);
1102 if (((i
+ 1) % 20) == 0)
1103 fprintf (table
, "\n ");
1106 fprintf (table
, "%d },\n", modifier
[i
].value
);
1110 adjust_broadcast_modifier (char **opnd
)
1112 char *str
, *next
, *last
, *op
;
1113 int bcst_type
= INT_MAX
;
1115 /* Skip the immediate operand. */
1117 if (strcasecmp(op
, "Imm8") == 0)
1121 last
= op
+ strlen (op
);
1122 for (next
= op
; next
&& next
< last
; )
1124 str
= next_field (next
, '|', &next
, last
);
1127 if (strcasecmp(str
, "Byte") == 0)
1129 /* The smalest broadcast type, no need to check
1131 bcst_type
= BYTE_BROADCAST
;
1134 else if (strcasecmp(str
, "Word") == 0)
1136 if (bcst_type
> WORD_BROADCAST
)
1137 bcst_type
= WORD_BROADCAST
;
1139 else if (strcasecmp(str
, "Dword") == 0)
1141 if (bcst_type
> DWORD_BROADCAST
)
1142 bcst_type
= DWORD_BROADCAST
;
1144 else if (strcasecmp(str
, "Qword") == 0)
1146 if (bcst_type
> QWORD_BROADCAST
)
1147 bcst_type
= QWORD_BROADCAST
;
1153 if (bcst_type
== INT_MAX
)
1154 fail (_("unknown broadcast operand: %s\n"), op
);
1160 process_i386_opcode_modifier (FILE *table
, char *mod
, char **opnd
, int lineno
)
1162 char *str
, *next
, *last
;
1163 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1165 active_isstring
= 0;
1167 /* Copy the default opcode modifier. */
1168 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1170 if (strcmp (mod
, "0"))
1172 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1174 last
= mod
+ strlen (mod
);
1175 for (next
= mod
; next
&& next
< last
; )
1177 str
= next_field (next
, '|', &next
, last
);
1181 if (strcasecmp(str
, "Broadcast") == 0)
1182 val
= adjust_broadcast_modifier (opnd
);
1183 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1185 if (strcasecmp(str
, "IsString") == 0)
1186 active_isstring
= 1;
1188 if (strcasecmp(str
, "W") == 0)
1191 if (strcasecmp(str
, "No_bSuf") == 0)
1193 if (strcasecmp(str
, "No_wSuf") == 0)
1195 if (strcasecmp(str
, "No_lSuf") == 0)
1197 if (strcasecmp(str
, "No_qSuf") == 0)
1202 if (have_w
&& !bwlq_suf
)
1203 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1204 if (have_w
&& !(bwlq_suf
& 1))
1205 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1207 if (have_w
&& !(bwlq_suf
& ~1))
1209 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1212 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1222 output_operand_type (FILE *table
, enum operand_class
class,
1223 enum operand_instance instance
,
1224 const bitfield
*types
, unsigned int size
,
1225 enum stage stage
, const char *indent
)
1229 fprintf (table
, "{ { %d, %d, ", class, instance
);
1231 for (i
= 0; i
< size
- 1; i
++)
1233 if (((i
+ 3) % 20) != 0)
1234 fprintf (table
, "%d, ", types
[i
].value
);
1236 fprintf (table
, "%d,", types
[i
].value
);
1237 if (((i
+ 3) % 20) == 0)
1239 /* We need \\ for macro. */
1240 if (stage
== stage_macros
)
1241 fprintf (table
, " \\\n%s", indent
);
1243 fprintf (table
, "\n%s", indent
);
1247 fprintf (table
, "%d } }", types
[i
].value
);
1251 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1252 const char *indent
, int lineno
)
1254 char *str
, *next
, *last
;
1255 enum operand_class
class = ClassNone
;
1256 enum operand_instance instance
= InstanceNone
;
1257 bitfield types
[ARRAY_SIZE (operand_types
)];
1259 /* Copy the default operand type. */
1260 memcpy (types
, operand_types
, sizeof (types
));
1262 if (strcmp (op
, "0"))
1266 last
= op
+ strlen (op
);
1267 for (next
= op
; next
&& next
< last
; )
1269 str
= next_field (next
, '|', &next
, last
);
1274 if (!strncmp(str
, "Class=", 6))
1276 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1277 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1279 class = operand_classes
[i
].value
;
1285 if (str
&& !strncmp(str
, "Instance=", 9))
1287 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1288 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1290 instance
= operand_instances
[i
].value
;
1298 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1299 if (strcasecmp(str
, "BaseIndex") == 0)
1304 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1306 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1307 if (!active_cpu_flags
.bitfield
.cpu64
1308 && !active_cpu_flags
.bitfield
.cpumpx
)
1309 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1310 if (!active_cpu_flags
.bitfield
.cpu64
)
1311 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1312 if (!active_cpu_flags
.bitfield
.cpuno64
)
1313 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1316 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1321 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1322 char *last
, int lineno
)
1325 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1326 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1328 /* Find number of operands. */
1329 operands
= next_field (str
, ',', &str
, last
);
1331 /* Find base_opcode. */
1332 base_opcode
= next_field (str
, ',', &str
, last
);
1334 /* Find extension_opcode. */
1335 extension_opcode
= next_field (str
, ',', &str
, last
);
1337 /* Find opcode_length. */
1338 opcode_length
= next_field (str
, ',', &str
, last
);
1340 /* Find cpu_flags. */
1341 cpu_flags
= next_field (str
, ',', &str
, last
);
1343 /* Find opcode_modifier. */
1344 opcode_modifier
= next_field (str
, ',', &str
, last
);
1346 /* Remove the first {. */
1347 str
= remove_leading_whitespaces (str
);
1350 str
= remove_leading_whitespaces (str
+ 1);
1354 /* There are at least "X}". */
1358 /* Remove trailing white spaces and }. */
1362 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1371 /* Find operand_types. */
1372 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1376 operand_types
[i
] = NULL
;
1380 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1381 if (*operand_types
[i
] == '0')
1384 operand_types
[i
] = NULL
;
1389 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1390 name
, base_opcode
, extension_opcode
, opcode_length
, operands
);
1392 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1394 process_i386_opcode_modifier (table
, opcode_modifier
, operand_types
, lineno
);
1396 fprintf (table
, " { ");
1398 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1400 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1403 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1409 fprintf (table
, ",\n ");
1411 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1414 fprintf (table
, " } },\n");
1417 struct opcode_hash_entry
1419 struct opcode_hash_entry
*next
;
1425 /* Calculate the hash value of an opcode hash entry P. */
1428 opcode_hash_hash (const void *p
)
1430 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1431 return htab_hash_string (entry
->name
);
1434 /* Compare a string Q against an opcode hash entry P. */
1437 opcode_hash_eq (const void *p
, const void *q
)
1439 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1440 const char *name
= (const char *) q
;
1441 return strcmp (name
, entry
->name
) == 0;
1445 parse_template (char *buf
, int lineno
)
1447 char sep
, *end
, *name
;
1448 struct template *tmpl
= xmalloc (sizeof (*tmpl
));
1449 struct template_instance
*last_inst
= NULL
;
1451 buf
= remove_leading_whitespaces (buf
+ 1);
1452 end
= strchr (buf
, ':');
1454 fail ("%s: %d: missing ':'\n", filename
, lineno
);
1456 remove_trailing_whitespaces (buf
);
1459 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1460 tmpl
->name
= xstrdup (buf
);
1462 tmpl
->params
= NULL
;
1464 struct template_param
*param
;
1466 buf
= remove_leading_whitespaces (end
);
1467 end
= strpbrk (buf
, ":,");
1469 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1473 remove_trailing_whitespaces (buf
);
1475 param
= xmalloc (sizeof (*param
));
1476 param
->name
= xstrdup (buf
);
1477 param
->next
= tmpl
->params
;
1478 tmpl
->params
= param
;
1479 } while (sep
== ':');
1481 tmpl
->instances
= NULL
;
1483 struct template_instance
*inst
;
1485 const struct template_param
*param
;
1487 buf
= remove_leading_whitespaces (end
);
1488 end
= strpbrk (buf
, ",>");
1490 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1495 inst
= xmalloc (sizeof (*inst
));
1497 cur
= next_field (buf
, ':', &next
, end
);
1498 inst
->name
= xstrdup (cur
);
1500 for (param
= tmpl
->params
; param
; param
= param
->next
)
1502 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1504 cur
= next_field (next
, ':', &next
, end
);
1506 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1507 arg
->val
= xstrdup (cur
);
1508 arg
->next
= inst
->args
;
1512 if (tmpl
->instances
)
1513 last_inst
->next
= inst
;
1515 tmpl
->instances
= inst
;
1517 } while (sep
== ',');
1519 buf
= remove_leading_whitespaces (end
);
1521 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1522 filename
, lineno
, buf
);
1524 tmpl
->next
= templates
;
1529 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1530 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1532 static unsigned int idx
, opcode_array_size
;
1533 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1534 struct opcode_hash_entry
**hash_slot
, **entry
;
1535 char *ptr1
= strchr(name
, '<'), *ptr2
;
1539 /* Get the slot in hash table. */
1540 hash_slot
= (struct opcode_hash_entry
**)
1541 htab_find_slot_with_hash (opcode_hash_table
, name
,
1542 htab_hash_string (name
),
1545 if (*hash_slot
== NULL
)
1547 /* It is the new one. Put it on opcode array. */
1548 if (idx
>= opcode_array_size
)
1550 /* Grow the opcode array when needed. */
1551 opcode_array_size
+= 1024;
1552 opcode_array
= (struct opcode_hash_entry
**)
1553 xrealloc (opcode_array
,
1554 sizeof (*opcode_array
) * opcode_array_size
);
1555 *opcode_array_p
= opcode_array
;
1558 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1559 xmalloc (sizeof (struct opcode_hash_entry
));
1560 opcode_array
[idx
]->next
= NULL
;
1561 opcode_array
[idx
]->name
= xstrdup (name
);
1562 opcode_array
[idx
]->opcode
= xstrdup (str
);
1563 opcode_array
[idx
]->lineno
= lineno
;
1564 *hash_slot
= opcode_array
[idx
];
1569 /* Append it to the existing one. */
1571 while ((*entry
) != NULL
)
1572 entry
= &(*entry
)->next
;
1573 *entry
= (struct opcode_hash_entry
*)
1574 xmalloc (sizeof (struct opcode_hash_entry
));
1575 (*entry
)->next
= NULL
;
1576 (*entry
)->name
= (*hash_slot
)->name
;
1577 (*entry
)->opcode
= xstrdup (str
);
1578 (*entry
)->lineno
= lineno
;
1581 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1582 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1585 const struct template *tmpl
;
1586 const struct template_instance
*inst
;
1589 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1590 remove_trailing_whitespaces (ptr1
);
1594 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1595 if (!strcmp(ptr1
, tmpl
->name
))
1598 fail ("reference to unknown template '%s'\n", ptr1
);
1600 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1602 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1603 char *str2
= xmalloc(2 * strlen(str
));
1606 strcpy (name2
, name
);
1607 strcat (name2
, inst
->name
);
1608 strcat (name2
, ptr2
);
1610 for (ptr1
= str2
, src
= str
; *src
; )
1612 const char *ident
= tmpl
->name
, *end
;
1613 const struct template_param
*param
;
1614 const struct template_arg
*arg
;
1616 if ((*ptr1
= *src
++) != '<')
1621 while (ISSPACE(*src
))
1623 while (*ident
&& *src
== *ident
)
1625 while (ISSPACE(*src
))
1627 if (*src
!= ':' || *ident
!= '\0')
1629 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1630 ptr1
+= ident
- tmpl
->name
;
1633 while (ISSPACE(*++src
))
1637 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1640 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1641 param
= param
->next
, arg
= arg
->next
)
1643 if (end
- src
== strlen (param
->name
)
1644 && !memcmp (src
, param
->name
, end
- src
))
1652 fail ("template '%s' has no parameter '%.*s'\n",
1653 tmpl
->name
, (int)(end
- src
), src
);
1655 while (ISSPACE(*src
))
1658 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1660 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1661 ptr1
+= strlen(arg
->val
);
1667 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1679 process_i386_opcodes (FILE *table
)
1684 char *str
, *p
, *last
, *name
;
1685 htab_t opcode_hash_table
;
1686 struct opcode_hash_entry
**opcode_array
= NULL
;
1687 int lineno
= 0, marker
= 0;
1689 filename
= "i386-opc.tbl";
1693 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1694 opcode_hash_eq
, NULL
,
1697 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1698 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1700 /* Put everything on opcode array. */
1703 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1708 p
= remove_leading_whitespaces (buf
);
1710 /* Skip comments. */
1711 str
= strstr (p
, "//");
1715 /* Remove trailing white spaces. */
1716 remove_trailing_whitespaces (p
);
1721 if (!strcmp("### MARKER ###", buf
))
1725 /* Since we ignore all included files (we only care about their
1726 #define-s here), we don't need to monitor filenames. The final
1727 line number directive is going to refer to the main source file
1732 p
= remove_leading_whitespaces (p
+ 1);
1733 if (!strncmp(p
, "line", 4))
1735 ln
= strtoul (p
, &end
, 10);
1736 if (ln
> 1 && ln
< INT_MAX
1737 && *remove_leading_whitespaces (end
) == '"')
1740 /* Ignore comments. */
1745 parse_template (p
, lineno
);
1753 last
= p
+ strlen (p
);
1756 name
= next_field (p
, ',', &str
, last
);
1758 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1762 /* Process opcode array. */
1763 for (j
= 0; j
< i
; j
++)
1765 struct opcode_hash_entry
*next
;
1767 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1771 lineno
= next
->lineno
;
1772 last
= str
+ strlen (str
);
1773 output_i386_opcode (table
, name
, str
, last
, lineno
);
1779 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1781 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1783 process_i386_opcode_modifier (table
, "0", NULL
, -1);
1785 fprintf (table
, " { ");
1786 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1787 fprintf (table
, " } }\n");
1789 fprintf (table
, "};\n");
1793 process_i386_registers (FILE *table
)
1797 char *str
, *p
, *last
;
1798 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1799 char *dw2_32_num
, *dw2_64_num
;
1802 filename
= "i386-reg.tbl";
1803 fp
= fopen (filename
, "r");
1805 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1808 fprintf (table
, "\n/* i386 register table. */\n\n");
1809 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1813 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1818 p
= remove_leading_whitespaces (buf
);
1820 /* Skip comments. */
1821 str
= strstr (p
, "//");
1825 /* Remove trailing white spaces. */
1826 remove_trailing_whitespaces (p
);
1831 fprintf (table
, "%s\n", p
);
1839 last
= p
+ strlen (p
);
1841 /* Find reg_name. */
1842 reg_name
= next_field (p
, ',', &str
, last
);
1844 /* Find reg_type. */
1845 reg_type
= next_field (str
, ',', &str
, last
);
1847 /* Find reg_flags. */
1848 reg_flags
= next_field (str
, ',', &str
, last
);
1851 reg_num
= next_field (str
, ',', &str
, last
);
1853 fprintf (table
, " { \"%s\",\n ", reg_name
);
1855 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1858 /* Find 32-bit Dwarf2 register number. */
1859 dw2_32_num
= next_field (str
, ',', &str
, last
);
1861 /* Find 64-bit Dwarf2 register number. */
1862 dw2_64_num
= next_field (str
, ',', &str
, last
);
1864 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1865 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1870 fprintf (table
, "};\n");
1872 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1876 process_i386_initializers (void)
1879 FILE *fp
= fopen ("i386-init.h", "w");
1883 fail (_("can't create i386-init.h, errno = %s\n"),
1886 process_copyright (fp
);
1888 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1890 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1891 init
= xstrdup (cpu_flag_init
[i
].init
);
1892 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1896 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1898 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1899 init
= xstrdup (operand_type_init
[i
].init
);
1900 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1908 /* Program options. */
1909 #define OPTION_SRCDIR 200
1911 struct option long_options
[] =
1913 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1914 {"debug", no_argument
, NULL
, 'd'},
1915 {"version", no_argument
, NULL
, 'V'},
1916 {"help", no_argument
, NULL
, 'h'},
1917 {0, no_argument
, NULL
, 0}
1921 print_version (void)
1923 printf ("%s: version 1.0\n", program_name
);
1928 usage (FILE * stream
, int status
)
1930 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1936 main (int argc
, char **argv
)
1938 extern int chdir (char *);
1939 char *srcdir
= NULL
;
1941 unsigned int i
, cpumax
;
1944 program_name
= *argv
;
1945 xmalloc_set_program_name (program_name
);
1947 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1972 if (chdir (srcdir
) != 0)
1973 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1974 srcdir
, xstrerror (errno
));
1976 /* cpu_flags isn't sorted by position. */
1978 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1979 if (cpu_flags
[i
].position
> cpumax
)
1980 cpumax
= cpu_flags
[i
].position
;
1982 /* Check the unused bitfield in i386_cpu_flags. */
1984 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
1986 if ((cpumax
- 1) != CpuMax
)
1987 fail (_("CpuMax != %d!\n"), cpumax
);
1989 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
1991 if (cpumax
!= CpuMax
)
1992 fail (_("CpuMax != %d!\n"), cpumax
);
1994 c
= CpuNumOfBits
- CpuMax
- 1;
1996 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1999 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2001 /* Check the unused bitfield in i386_operand_type. */
2003 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2006 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2009 c
= OTNumOfBits
- OTNum
;
2011 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2014 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2017 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2018 sizeof (opcode_modifiers
[0]), compare
);
2020 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2021 sizeof (operand_types
[0]), compare
);
2023 table
= fopen ("i386-tbl.h", "w");
2025 fail (_("can't create i386-tbl.h, errno = %s\n"),
2028 process_copyright (table
);
2030 process_i386_opcodes (table
);
2031 process_i386_registers (table
);
2032 process_i386_initializers ();