1 /* Copyright (C) 2007-2017 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 static const char *program_name
= NULL
;
36 typedef struct initializer
42 static initializer cpu_flag_init
[] =
44 { "CPU_UNKNOWN_FLAGS",
45 "~(CpuL1OM|CpuK1OM)" },
46 { "CPU_GENERIC32_FLAGS",
47 "Cpu186|Cpu286|Cpu386" },
48 { "CPU_GENERIC64_FLAGS",
49 "CPU_PENTIUMPRO_FLAGS|CpuClflush|CpuSYSCALL|CPU_MMX_FLAGS|CPU_SSE2_FLAGS|CpuLM" },
55 "CPU_I186_FLAGS|Cpu286" },
57 "CPU_I286_FLAGS|Cpu386" },
59 "CPU_I386_FLAGS|Cpu486" },
61 "CPU_I486_FLAGS|CPU_387_FLAGS|Cpu586" },
63 "CPU_I586_FLAGS|Cpu686|Cpu687" },
64 { "CPU_PENTIUMPRO_FLAGS",
65 "CPU_I686_FLAGS|CpuNop" },
67 "CPU_PENTIUMPRO_FLAGS|CPU_MMX_FLAGS" },
69 "CPU_P2_FLAGS|CPU_SSE_FLAGS" },
71 "CPU_P3_FLAGS|CpuClflush|CPU_SSE2_FLAGS" },
73 "CPU_GENERIC64_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
75 "CPU_P4_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
77 "CPU_NOCONA_FLAGS|CPU_SSSE3_FLAGS" },
79 "CPU_CORE2_FLAGS|CPU_SSE4_2_FLAGS|CpuRdtscp" },
81 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CPU_MMX_FLAGS" },
83 "CPU_K6_FLAGS|Cpu3dnow" },
85 "CPU_K6_2_FLAGS|Cpu686|Cpu687|CpuNop|Cpu3dnowA" },
87 "CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
88 { "CPU_AMDFAM10_FLAGS",
89 "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuABM" },
91 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_SSE4_2_FLAGS|CpuSSE4A|CpuABM|CpuFMA4|CpuXOP|CpuLWP|CpuSVME|CpuXsave|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW" },
93 "CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
95 "CPU_BDVER2_FLAGS|CpuXsaveopt|CpuFSGSBase" },
97 "CPU_BDVER3_FLAGS|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuMWAITX" },
99 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_SSE4_2_FLAGS|CpuSSE4A|CpuABM|CpuSVME|CpuXsave|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW|CpuFMA|CpuBMI|CpuF16C|CpuXsaveopt|CpuFSGSBase|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuADX|CpuRdSeed|CpuSMAP|CpuSHA|CpuXSAVEC|CpuXSAVES|CpuClflushOpt|CpuCLZERO|CpuMWAITX" },
100 { "CPU_BTVER1_FLAGS",
101 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuABM|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME|CpuLZCNT" },
102 { "CPU_BTVER2_FLAGS",
103 "CPU_BTVER1_FLAGS|CPU_SSE4_2_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuAVX|CpuMovbe|CpuXsave|CpuXsaveopt|CpuPRFCHW" },
107 "CPU_8087_FLAGS|Cpu287" },
109 "CPU_287_FLAGS|Cpu387" },
111 "CPU_387_FLAGS|Cpu687" },
112 { "CPU_CLFLUSH_FLAGS",
116 { "CPU_SYSCALL_FLAGS",
119 "CpuRegMMX|CpuMMX" },
121 "CpuRegXMM|CpuSSE" },
123 "CPU_SSE_FLAGS|CpuSSE2" },
125 "CPU_SSE2_FLAGS|CpuSSE3" },
127 "CPU_SSE3_FLAGS|CpuSSSE3" },
128 { "CPU_SSE4_1_FLAGS",
129 "CPU_SSSE3_FLAGS|CpuSSE4_1" },
130 { "CPU_SSE4_2_FLAGS",
131 "CPU_SSE4_1_FLAGS|CpuSSE4_2" },
138 { "CPU_XSAVEOPT_FLAGS",
139 "CPU_XSAVE_FLAGS|CpuXsaveopt" },
141 "CPU_SSE2_FLAGS|CpuAES" },
142 { "CPU_PCLMUL_FLAGS",
143 "CPU_SSE2_FLAGS|CpuPCLMUL" },
145 "CPU_AVX_FLAGS|CpuFMA" },
147 "CPU_AVX_FLAGS|CpuFMA4" },
149 "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
160 { "CPU_RDTSCP_FLAGS",
164 { "CPU_FSGSBASE_FLAGS",
169 "CPU_AVX_FLAGS|CpuF16C" },
178 { "CPU_INVPCID_FLAGS",
180 { "CPU_VMFUNC_FLAGS",
183 "CPU_MMX_FLAGS|Cpu3dnow" },
184 { "CPU_3DNOWA_FLAGS",
185 "CPU_3DNOW_FLAGS|Cpu3dnowA" },
186 { "CPU_PADLOCK_FLAGS",
191 "CPU_SSE3_FLAGS|CpuSSE4a" },
195 "CPU_SSE4_2_FLAGS|CpuRegYMM|CpuAVX" },
197 "CPU_AVX_FLAGS|CpuAVX2" },
198 /* Don't use CPU_AVX2_FLAGS on CPU_AVX512F_FLAGS since AVX512F doesn't
199 support YMM registers. */
200 { "CPU_AVX512F_FLAGS",
201 "CpuVREX|CPU_SSE4_2_FLAGS|CpuRegZMM|CpuRegMask|CpuAVX|CpuAVX2|CpuAVX512F" },
202 { "CPU_AVX512CD_FLAGS",
203 "CPU_AVX512F_FLAGS|CpuAVX512CD" },
204 { "CPU_AVX512ER_FLAGS",
205 "CPU_AVX512F_FLAGS|CpuAVX512ER" },
206 { "CPU_AVX512PF_FLAGS",
207 "CPU_AVX512F_FLAGS|CpuAVX512PF" },
208 { "CPU_AVX512DQ_FLAGS",
209 "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
210 { "CPU_AVX512BW_FLAGS",
211 "CPU_AVX512F_FLAGS|CpuAVX512BW" },
212 { "CPU_AVX512VL_FLAGS",
213 /* Use CPU_AVX2_FLAGS on CPU_AVX512VL_FLAGS since AVX512VL supports YMM
215 "CPU_AVX512F_FLAGS|CPU_AVX2_FLAGS|CpuAVX512VL" },
216 { "CPU_AVX512IFMA_FLAGS",
217 "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
218 { "CPU_AVX512VBMI_FLAGS",
219 "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
220 { "CPU_AVX512_4FMAPS_FLAGS",
221 "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
222 { "CPU_AVX512_4VNNIW_FLAGS",
223 "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
224 { "CPU_AVX512_VPOPCNTDQ_FLAGS",
225 "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
226 { "CPU_AVX512_VBMI2_FLAGS",
227 "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
233 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
236 { "CPU_RDSEED_FLAGS",
238 { "CPU_PRFCHW_FLAGS",
245 "CPU_SSE2_FLAGS|CpuSHA" },
246 { "CPU_CLFLUSHOPT_FLAGS",
248 { "CPU_XSAVES_FLAGS",
249 "CPU_XSAVE_FLAGS|CpuXSAVES" },
250 { "CPU_XSAVEC_FLAGS",
251 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
252 { "CPU_PREFETCHWT1_FLAGS",
258 { "CPU_CLZERO_FLAGS",
260 { "CPU_MWAITX_FLAGS",
266 { "CPU_PTWRITE_FLAGS",
274 { "CPU_ANY_X87_FLAGS",
275 "CPU_ANY_287_FLAGS|Cpu8087" },
276 { "CPU_ANY_287_FLAGS",
277 "CPU_ANY_387_FLAGS|Cpu287" },
278 { "CPU_ANY_387_FLAGS",
279 "CPU_ANY_687_FLAGS|Cpu387" },
280 { "CPU_ANY_687_FLAGS",
281 "Cpu687|CpuFISTTP" },
282 { "CPU_ANY_MMX_FLAGS",
283 "CPU_3DNOWA_FLAGS" },
284 { "CPU_ANY_SSE_FLAGS",
285 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
286 { "CPU_ANY_SSE2_FLAGS",
287 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
288 { "CPU_ANY_SSE3_FLAGS",
289 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
290 { "CPU_ANY_SSSE3_FLAGS",
291 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
292 { "CPU_ANY_SSE4_1_FLAGS",
293 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
294 { "CPU_ANY_SSE4_2_FLAGS",
296 { "CPU_ANY_AVX_FLAGS",
297 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
298 { "CPU_ANY_AVX2_FLAGS",
300 { "CPU_ANY_AVX512F_FLAGS",
301 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512F" },
302 { "CPU_ANY_AVX512CD_FLAGS",
304 { "CPU_ANY_AVX512ER_FLAGS",
306 { "CPU_ANY_AVX512PF_FLAGS",
308 { "CPU_ANY_AVX512DQ_FLAGS",
310 { "CPU_ANY_AVX512BW_FLAGS",
312 { "CPU_ANY_AVX512VL_FLAGS",
314 { "CPU_ANY_AVX512IFMA_FLAGS",
316 { "CPU_ANY_AVX512VBMI_FLAGS",
318 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
319 "CpuAVX512_4FMAPS" },
320 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
321 "CpuAVX512_4VNNIW" },
322 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
323 "CpuAVX512_VPOPCNTDQ" },
324 { "CPU_ANY_AVX512_VBMI2_FLAGS",
328 static initializer operand_type_init
[] =
330 { "OPERAND_TYPE_NONE",
332 { "OPERAND_TYPE_REG8",
334 { "OPERAND_TYPE_REG16",
336 { "OPERAND_TYPE_REG32",
338 { "OPERAND_TYPE_REG64",
340 { "OPERAND_TYPE_IMM1",
342 { "OPERAND_TYPE_IMM8",
344 { "OPERAND_TYPE_IMM8S",
346 { "OPERAND_TYPE_IMM16",
348 { "OPERAND_TYPE_IMM32",
350 { "OPERAND_TYPE_IMM32S",
352 { "OPERAND_TYPE_IMM64",
354 { "OPERAND_TYPE_BASEINDEX",
356 { "OPERAND_TYPE_DISP8",
358 { "OPERAND_TYPE_DISP16",
360 { "OPERAND_TYPE_DISP32",
362 { "OPERAND_TYPE_DISP32S",
364 { "OPERAND_TYPE_DISP64",
366 { "OPERAND_TYPE_INOUTPORTREG",
368 { "OPERAND_TYPE_SHIFTCOUNT",
370 { "OPERAND_TYPE_CONTROL",
372 { "OPERAND_TYPE_TEST",
374 { "OPERAND_TYPE_DEBUG",
376 { "OPERAND_TYPE_FLOATREG",
378 { "OPERAND_TYPE_FLOATACC",
380 { "OPERAND_TYPE_SREG2",
382 { "OPERAND_TYPE_SREG3",
384 { "OPERAND_TYPE_ACC",
386 { "OPERAND_TYPE_JUMPABSOLUTE",
388 { "OPERAND_TYPE_REGMMX",
390 { "OPERAND_TYPE_REGXMM",
392 { "OPERAND_TYPE_REGYMM",
394 { "OPERAND_TYPE_REGZMM",
396 { "OPERAND_TYPE_REGMASK",
398 { "OPERAND_TYPE_ESSEG",
400 { "OPERAND_TYPE_ACC32",
402 { "OPERAND_TYPE_ACC64",
404 { "OPERAND_TYPE_INOUTPORTREG",
406 { "OPERAND_TYPE_REG16_INOUTPORTREG",
407 "Reg16|InOutPortReg" },
408 { "OPERAND_TYPE_DISP16_32",
410 { "OPERAND_TYPE_ANYDISP",
411 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
412 { "OPERAND_TYPE_IMM16_32",
414 { "OPERAND_TYPE_IMM16_32S",
416 { "OPERAND_TYPE_IMM16_32_32S",
417 "Imm16|Imm32|Imm32S" },
418 { "OPERAND_TYPE_IMM32_64",
420 { "OPERAND_TYPE_IMM32_32S_DISP32",
421 "Imm32|Imm32S|Disp32" },
422 { "OPERAND_TYPE_IMM64_DISP64",
424 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
425 "Imm32|Imm32S|Imm64|Disp32" },
426 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
427 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
428 { "OPERAND_TYPE_VEC_IMM4",
430 { "OPERAND_TYPE_REGBND",
432 { "OPERAND_TYPE_VEC_DISP8",
436 typedef struct bitfield
443 #define BITFIELD(n) { n, 0, #n }
445 static bitfield cpu_flags
[] =
453 BITFIELD (CpuClflush
),
455 BITFIELD (CpuSYSCALL
),
460 BITFIELD (CpuFISTTP
),
466 BITFIELD (CpuSSE4_1
),
467 BITFIELD (CpuSSE4_2
),
470 BITFIELD (CpuAVX512F
),
471 BITFIELD (CpuAVX512CD
),
472 BITFIELD (CpuAVX512ER
),
473 BITFIELD (CpuAVX512PF
),
474 BITFIELD (CpuAVX512VL
),
475 BITFIELD (CpuAVX512DQ
),
476 BITFIELD (CpuAVX512BW
),
482 BITFIELD (Cpu3dnowA
),
483 BITFIELD (CpuPadLock
),
489 BITFIELD (CpuXsaveopt
),
491 BITFIELD (CpuPCLMUL
),
502 BITFIELD (CpuRdtscp
),
503 BITFIELD (CpuFSGSBase
),
510 BITFIELD (CpuINVPCID
),
511 BITFIELD (CpuVMFUNC
),
512 BITFIELD (CpuRDSEED
),
514 BITFIELD (CpuPRFCHW
),
518 BITFIELD (CpuClflushOpt
),
519 BITFIELD (CpuXSAVES
),
520 BITFIELD (CpuXSAVEC
),
521 BITFIELD (CpuPREFETCHWT1
),
527 BITFIELD (CpuAVX512IFMA
),
528 BITFIELD (CpuAVX512VBMI
),
529 BITFIELD (CpuAVX512_4FMAPS
),
530 BITFIELD (CpuAVX512_4VNNIW
),
531 BITFIELD (CpuAVX512_VPOPCNTDQ
),
532 BITFIELD (CpuAVX512_VBMI2
),
533 BITFIELD (CpuMWAITX
),
534 BITFIELD (CpuCLZERO
),
537 BITFIELD (CpuPTWRITE
),
541 BITFIELD (CpuRegMMX
),
542 BITFIELD (CpuRegXMM
),
543 BITFIELD (CpuRegYMM
),
544 BITFIELD (CpuRegZMM
),
545 BITFIELD (CpuRegMask
),
547 BITFIELD (CpuUnused
),
551 static bitfield opcode_modifiers
[] =
557 BITFIELD (ShortForm
),
559 BITFIELD (JumpDword
),
561 BITFIELD (JumpInterSegment
),
568 BITFIELD (CheckRegSize
),
569 BITFIELD (IgnoreSize
),
570 BITFIELD (DefaultSize
),
579 BITFIELD (BNDPrefixOk
),
580 BITFIELD (NoTrackPrefixOk
),
581 BITFIELD (IsLockable
),
582 BITFIELD (RegKludge
),
583 BITFIELD (FirstXmm0
),
584 BITFIELD (Implicit1stXmm0
),
585 BITFIELD (RepPrefixOk
),
586 BITFIELD (HLEPrefixOk
),
589 BITFIELD (AddrPrefixOp0
),
598 BITFIELD (VexOpcode
),
599 BITFIELD (VexSources
),
600 BITFIELD (VexImmExt
),
607 BITFIELD (Broadcast
),
608 BITFIELD (StaticRounding
),
610 BITFIELD (Disp8MemShift
),
611 BITFIELD (NoDefMask
),
612 BITFIELD (ImplicitQuadGroup
),
614 BITFIELD (ATTMnemonic
),
615 BITFIELD (ATTSyntax
),
616 BITFIELD (IntelSyntax
),
621 static bitfield operand_types
[] =
640 BITFIELD (BaseIndex
),
646 BITFIELD (InOutPortReg
),
647 BITFIELD (ShiftCount
),
655 BITFIELD (JumpAbsolute
),
668 BITFIELD (Unspecified
),
672 BITFIELD (Vec_Disp8
),
678 static const char *filename
;
681 compare (const void *x
, const void *y
)
683 const bitfield
*xp
= (const bitfield
*) x
;
684 const bitfield
*yp
= (const bitfield
*) y
;
685 return xp
->position
- yp
->position
;
689 fail (const char *message
, ...)
693 va_start (args
, message
);
694 fprintf (stderr
, _("%s: Error: "), program_name
);
695 vfprintf (stderr
, message
, args
);
701 process_copyright (FILE *fp
)
703 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
704 /* Copyright (C) 2007-2017 Free Software Foundation, Inc.\n\
706 This file is part of the GNU opcodes library.\n\
708 This library is free software; you can redistribute it and/or modify\n\
709 it under the terms of the GNU General Public License as published by\n\
710 the Free Software Foundation; either version 3, or (at your option)\n\
711 any later version.\n\
713 It is distributed in the hope that it will be useful, but WITHOUT\n\
714 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
715 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
716 License for more details.\n\
718 You should have received a copy of the GNU General Public License\n\
719 along with this program; if not, write to the Free Software\n\
720 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
721 MA 02110-1301, USA. */\n");
724 /* Remove leading white spaces. */
727 remove_leading_whitespaces (char *str
)
729 while (ISSPACE (*str
))
734 /* Remove trailing white spaces. */
737 remove_trailing_whitespaces (char *str
)
739 size_t last
= strlen (str
);
747 if (ISSPACE (str
[last
]))
755 /* Find next field separated by SEP and terminate it. Return a
756 pointer to the one after it. */
759 next_field (char *str
, char sep
, char **next
, char *last
)
763 p
= remove_leading_whitespaces (str
);
764 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
767 remove_trailing_whitespaces (p
);
777 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
780 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
,
781 int value
, unsigned int size
,
784 char *str
, *next
, *last
;
787 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
788 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
790 /* Turn on selective bits. */
791 char *init
= xstrdup (cpu_flag_init
[i
].init
);
792 last
= init
+ strlen (init
);
793 for (next
= init
; next
&& next
< last
; )
795 str
= next_field (next
, '|', &next
, last
);
797 set_bitfield (str
, array
, 1, size
, lineno
);
807 set_bitfield (char *f
, bitfield
*array
, int value
,
808 unsigned int size
, int lineno
)
812 if (strcmp (f
, "CpuFP") == 0)
814 set_bitfield("Cpu387", array
, value
, size
, lineno
);
815 set_bitfield("Cpu287", array
, value
, size
, lineno
);
818 else if (strcmp (f
, "Mmword") == 0)
820 else if (strcmp (f
, "Oword") == 0)
823 for (i
= 0; i
< size
; i
++)
824 if (strcasecmp (array
[i
].name
, f
) == 0)
826 array
[i
].value
= value
;
832 const char *v
= strchr (f
, '=');
839 for (i
= 0; i
< size
; i
++)
840 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
842 value
= strtol (v
+ 1, &end
, 0);
845 array
[i
].value
= value
;
853 /* Handle CPU_XXX_FLAGS. */
854 if (!set_bitfield_from_cpu_flag_init (f
, array
, value
, size
, lineno
))
858 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
860 fail (_("Unknown bitfield: %s\n"), f
);
864 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
865 int macro
, const char *comma
, const char *indent
)
869 fprintf (table
, "%s{ { ", indent
);
871 for (i
= 0; i
< size
- 1; i
++)
873 if (((i
+ 1) % 20) != 0)
874 fprintf (table
, "%d, ", flags
[i
].value
);
876 fprintf (table
, "%d,", flags
[i
].value
);
877 if (((i
+ 1) % 20) == 0)
879 /* We need \\ for macro. */
881 fprintf (table
, " \\\n %s", indent
);
883 fprintf (table
, "\n %s", indent
);
887 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
891 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
892 const char *comma
, const char *indent
,
895 char *str
, *next
, *last
;
897 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
899 /* Copy the default cpu flags. */
900 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
902 if (strcasecmp (flag
, "unknown") == 0)
904 /* We turn on everything except for cpu64 in case of
905 CPU_UNKNOWN_FLAGS. */
906 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
907 if (flags
[i
].position
!= Cpu64
)
910 else if (flag
[0] == '~')
912 last
= flag
+ strlen (flag
);
919 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
926 /* First we turn on everything except for cpu64. */
927 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
928 if (flags
[i
].position
!= Cpu64
)
931 /* Turn off selective bits. */
932 for (; next
&& next
< last
; )
934 str
= next_field (next
, '|', &next
, last
);
936 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
939 else if (strcmp (flag
, "0"))
941 /* Turn on selective bits. */
942 last
= flag
+ strlen (flag
);
943 for (next
= flag
; next
&& next
< last
; )
945 str
= next_field (next
, '|', &next
, last
);
947 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
951 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
956 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
960 fprintf (table
, " { ");
962 for (i
= 0; i
< size
- 1; i
++)
964 if (((i
+ 1) % 20) != 0)
965 fprintf (table
, "%d, ", modifier
[i
].value
);
967 fprintf (table
, "%d,", modifier
[i
].value
);
968 if (((i
+ 1) % 20) == 0)
969 fprintf (table
, "\n ");
972 fprintf (table
, "%d },\n", modifier
[i
].value
);
976 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
978 char *str
, *next
, *last
;
979 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
981 /* Copy the default opcode modifier. */
982 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
984 if (strcmp (mod
, "0"))
986 last
= mod
+ strlen (mod
);
987 for (next
= mod
; next
&& next
< last
; )
989 str
= next_field (next
, '|', &next
, last
);
991 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
995 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
999 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
1000 int macro
, const char *indent
)
1004 fprintf (table
, "{ { ");
1006 for (i
= 0; i
< size
- 1; i
++)
1008 if (((i
+ 1) % 20) != 0)
1009 fprintf (table
, "%d, ", types
[i
].value
);
1011 fprintf (table
, "%d,", types
[i
].value
);
1012 if (((i
+ 1) % 20) == 0)
1014 /* We need \\ for macro. */
1016 fprintf (table
, " \\\n%s", indent
);
1018 fprintf (table
, "\n%s", indent
);
1022 fprintf (table
, "%d } }", types
[i
].value
);
1026 process_i386_operand_type (FILE *table
, char *op
, int macro
,
1027 const char *indent
, int lineno
)
1029 char *str
, *next
, *last
;
1030 bitfield types
[ARRAY_SIZE (operand_types
)];
1032 /* Copy the default operand type. */
1033 memcpy (types
, operand_types
, sizeof (types
));
1035 if (strcmp (op
, "0"))
1037 last
= op
+ strlen (op
);
1038 for (next
= op
; next
&& next
< last
; )
1040 str
= next_field (next
, '|', &next
, last
);
1042 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1045 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
1050 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1051 char *last
, int lineno
)
1054 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1055 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1057 /* Find number of operands. */
1058 operands
= next_field (str
, ',', &str
, last
);
1060 /* Find base_opcode. */
1061 base_opcode
= next_field (str
, ',', &str
, last
);
1063 /* Find extension_opcode. */
1064 extension_opcode
= next_field (str
, ',', &str
, last
);
1066 /* Find opcode_length. */
1067 opcode_length
= next_field (str
, ',', &str
, last
);
1069 /* Find cpu_flags. */
1070 cpu_flags
= next_field (str
, ',', &str
, last
);
1072 /* Find opcode_modifier. */
1073 opcode_modifier
= next_field (str
, ',', &str
, last
);
1075 /* Remove the first {. */
1076 str
= remove_leading_whitespaces (str
);
1079 str
= remove_leading_whitespaces (str
+ 1);
1083 /* There are at least "X}". */
1087 /* Remove trailing white spaces and }. */
1091 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1100 /* Find operand_types. */
1101 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1105 operand_types
[i
] = NULL
;
1109 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1110 if (*operand_types
[i
] == '0')
1113 operand_types
[i
] = NULL
;
1118 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1119 name
, operands
, base_opcode
, extension_opcode
,
1122 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1124 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
1126 fprintf (table
, " { ");
1128 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1130 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1133 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
1138 fprintf (table
, ",\n ");
1140 process_i386_operand_type (table
, operand_types
[i
], 0,
1143 fprintf (table
, " } },\n");
1146 struct opcode_hash_entry
1148 struct opcode_hash_entry
*next
;
1154 /* Calculate the hash value of an opcode hash entry P. */
1157 opcode_hash_hash (const void *p
)
1159 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1160 return htab_hash_string (entry
->name
);
1163 /* Compare a string Q against an opcode hash entry P. */
1166 opcode_hash_eq (const void *p
, const void *q
)
1168 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1169 const char *name
= (const char *) q
;
1170 return strcmp (name
, entry
->name
) == 0;
1174 process_i386_opcodes (FILE *table
)
1179 char *str
, *p
, *last
, *name
;
1180 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1181 htab_t opcode_hash_table
;
1182 struct opcode_hash_entry
**opcode_array
;
1183 unsigned int opcode_array_size
= 1024;
1186 filename
= "i386-opc.tbl";
1187 fp
= fopen (filename
, "r");
1190 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1194 opcode_array
= (struct opcode_hash_entry
**)
1195 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1197 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1198 opcode_hash_eq
, NULL
,
1201 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1202 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1204 /* Put everything on opcode array. */
1207 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1212 p
= remove_leading_whitespaces (buf
);
1214 /* Skip comments. */
1215 str
= strstr (p
, "//");
1219 /* Remove trailing white spaces. */
1220 remove_trailing_whitespaces (p
);
1225 /* Ignore comments. */
1233 last
= p
+ strlen (p
);
1236 name
= next_field (p
, ',', &str
, last
);
1238 /* Get the slot in hash table. */
1239 hash_slot
= (struct opcode_hash_entry
**)
1240 htab_find_slot_with_hash (opcode_hash_table
, name
,
1241 htab_hash_string (name
),
1244 if (*hash_slot
== NULL
)
1246 /* It is the new one. Put it on opcode array. */
1247 if (i
>= opcode_array_size
)
1249 /* Grow the opcode array when needed. */
1250 opcode_array_size
+= 1024;
1251 opcode_array
= (struct opcode_hash_entry
**)
1252 xrealloc (opcode_array
,
1253 sizeof (*opcode_array
) * opcode_array_size
);
1256 opcode_array
[i
] = (struct opcode_hash_entry
*)
1257 xmalloc (sizeof (struct opcode_hash_entry
));
1258 opcode_array
[i
]->next
= NULL
;
1259 opcode_array
[i
]->name
= xstrdup (name
);
1260 opcode_array
[i
]->opcode
= xstrdup (str
);
1261 opcode_array
[i
]->lineno
= lineno
;
1262 *hash_slot
= opcode_array
[i
];
1267 /* Append it to the existing one. */
1269 while ((*entry
) != NULL
)
1270 entry
= &(*entry
)->next
;
1271 *entry
= (struct opcode_hash_entry
*)
1272 xmalloc (sizeof (struct opcode_hash_entry
));
1273 (*entry
)->next
= NULL
;
1274 (*entry
)->name
= (*hash_slot
)->name
;
1275 (*entry
)->opcode
= xstrdup (str
);
1276 (*entry
)->lineno
= lineno
;
1280 /* Process opcode array. */
1281 for (j
= 0; j
< i
; j
++)
1283 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1287 lineno
= next
->lineno
;
1288 last
= str
+ strlen (str
);
1289 output_i386_opcode (table
, name
, str
, last
, lineno
);
1295 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1297 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1299 process_i386_opcode_modifier (table
, "0", -1);
1301 fprintf (table
, " { ");
1302 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1303 fprintf (table
, " } }\n");
1305 fprintf (table
, "};\n");
1309 process_i386_registers (FILE *table
)
1313 char *str
, *p
, *last
;
1314 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1315 char *dw2_32_num
, *dw2_64_num
;
1318 filename
= "i386-reg.tbl";
1319 fp
= fopen (filename
, "r");
1321 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1324 fprintf (table
, "\n/* i386 register table. */\n\n");
1325 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1329 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1334 p
= remove_leading_whitespaces (buf
);
1336 /* Skip comments. */
1337 str
= strstr (p
, "//");
1341 /* Remove trailing white spaces. */
1342 remove_trailing_whitespaces (p
);
1347 fprintf (table
, "%s\n", p
);
1355 last
= p
+ strlen (p
);
1357 /* Find reg_name. */
1358 reg_name
= next_field (p
, ',', &str
, last
);
1360 /* Find reg_type. */
1361 reg_type
= next_field (str
, ',', &str
, last
);
1363 /* Find reg_flags. */
1364 reg_flags
= next_field (str
, ',', &str
, last
);
1367 reg_num
= next_field (str
, ',', &str
, last
);
1369 fprintf (table
, " { \"%s\",\n ", reg_name
);
1371 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1373 /* Find 32-bit Dwarf2 register number. */
1374 dw2_32_num
= next_field (str
, ',', &str
, last
);
1376 /* Find 64-bit Dwarf2 register number. */
1377 dw2_64_num
= next_field (str
, ',', &str
, last
);
1379 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1380 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1385 fprintf (table
, "};\n");
1387 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1391 process_i386_initializers (void)
1394 FILE *fp
= fopen ("i386-init.h", "w");
1398 fail (_("can't create i386-init.h, errno = %s\n"),
1401 process_copyright (fp
);
1403 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1405 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1406 init
= xstrdup (cpu_flag_init
[i
].init
);
1407 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1411 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1413 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1414 init
= xstrdup (operand_type_init
[i
].init
);
1415 process_i386_operand_type (fp
, init
, 1, " ", -1);
1423 /* Program options. */
1424 #define OPTION_SRCDIR 200
1426 struct option long_options
[] =
1428 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1429 {"debug", no_argument
, NULL
, 'd'},
1430 {"version", no_argument
, NULL
, 'V'},
1431 {"help", no_argument
, NULL
, 'h'},
1432 {0, no_argument
, NULL
, 0}
1436 print_version (void)
1438 printf ("%s: version 1.0\n", program_name
);
1443 usage (FILE * stream
, int status
)
1445 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1451 main (int argc
, char **argv
)
1453 extern int chdir (char *);
1454 char *srcdir
= NULL
;
1456 unsigned int i
, cpumax
;
1459 program_name
= *argv
;
1460 xmalloc_set_program_name (program_name
);
1462 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1487 if (chdir (srcdir
) != 0)
1488 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1489 srcdir
, xstrerror (errno
));
1491 /* cpu_flags isn't sorted by position. */
1493 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1494 if (cpu_flags
[i
].position
> cpumax
)
1495 cpumax
= cpu_flags
[i
].position
;
1497 /* Check the unused bitfield in i386_cpu_flags. */
1499 if ((cpumax
- 1) != CpuMax
)
1500 fail (_("CpuMax != %d!\n"), cpumax
);
1502 if (cpumax
!= CpuMax
)
1503 fail (_("CpuMax != %d!\n"), cpumax
);
1505 c
= CpuNumOfBits
- CpuMax
- 1;
1507 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1510 /* Check the unused bitfield in i386_operand_type. */
1512 c
= OTNumOfBits
- OTMax
- 1;
1514 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1517 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1520 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1521 sizeof (opcode_modifiers
[0]), compare
);
1523 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1524 sizeof (operand_types
[0]), compare
);
1526 table
= fopen ("i386-tbl.h", "w");
1528 fail (_("can't create i386-tbl.h, errno = %s\n"),
1531 process_copyright (table
);
1533 process_i386_opcodes (table
);
1534 process_i386_registers (table
);
1535 process_i386_initializers ();