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" },
228 { "CPU_AVX512_VNNI_FLAGS",
229 "CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
235 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
238 { "CPU_RDSEED_FLAGS",
240 { "CPU_PRFCHW_FLAGS",
247 "CPU_SSE2_FLAGS|CpuSHA" },
248 { "CPU_CLFLUSHOPT_FLAGS",
250 { "CPU_XSAVES_FLAGS",
251 "CPU_XSAVE_FLAGS|CpuXSAVES" },
252 { "CPU_XSAVEC_FLAGS",
253 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
254 { "CPU_PREFETCHWT1_FLAGS",
260 { "CPU_CLZERO_FLAGS",
262 { "CPU_MWAITX_FLAGS",
268 { "CPU_PTWRITE_FLAGS",
276 { "CPU_VPCLMULQDQ_FLAGS",
278 { "CPU_ANY_X87_FLAGS",
279 "CPU_ANY_287_FLAGS|Cpu8087" },
280 { "CPU_ANY_287_FLAGS",
281 "CPU_ANY_387_FLAGS|Cpu287" },
282 { "CPU_ANY_387_FLAGS",
283 "CPU_ANY_687_FLAGS|Cpu387" },
284 { "CPU_ANY_687_FLAGS",
285 "Cpu687|CpuFISTTP" },
286 { "CPU_ANY_MMX_FLAGS",
287 "CPU_3DNOWA_FLAGS" },
288 { "CPU_ANY_SSE_FLAGS",
289 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
290 { "CPU_ANY_SSE2_FLAGS",
291 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
292 { "CPU_ANY_SSE3_FLAGS",
293 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
294 { "CPU_ANY_SSSE3_FLAGS",
295 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
296 { "CPU_ANY_SSE4_1_FLAGS",
297 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
298 { "CPU_ANY_SSE4_2_FLAGS",
300 { "CPU_ANY_AVX_FLAGS",
301 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
302 { "CPU_ANY_AVX2_FLAGS",
304 { "CPU_ANY_AVX512F_FLAGS",
305 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512F" },
306 { "CPU_ANY_AVX512CD_FLAGS",
308 { "CPU_ANY_AVX512ER_FLAGS",
310 { "CPU_ANY_AVX512PF_FLAGS",
312 { "CPU_ANY_AVX512DQ_FLAGS",
314 { "CPU_ANY_AVX512BW_FLAGS",
316 { "CPU_ANY_AVX512VL_FLAGS",
318 { "CPU_ANY_AVX512IFMA_FLAGS",
320 { "CPU_ANY_AVX512VBMI_FLAGS",
322 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
323 "CpuAVX512_4FMAPS" },
324 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
325 "CpuAVX512_4VNNIW" },
326 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
327 "CpuAVX512_VPOPCNTDQ" },
328 { "CPU_ANY_AVX512_VBMI2_FLAGS",
330 { "CPU_ANY_AVX512_VNNI_FLAGS",
334 static initializer operand_type_init
[] =
336 { "OPERAND_TYPE_NONE",
338 { "OPERAND_TYPE_REG8",
340 { "OPERAND_TYPE_REG16",
342 { "OPERAND_TYPE_REG32",
344 { "OPERAND_TYPE_REG64",
346 { "OPERAND_TYPE_IMM1",
348 { "OPERAND_TYPE_IMM8",
350 { "OPERAND_TYPE_IMM8S",
352 { "OPERAND_TYPE_IMM16",
354 { "OPERAND_TYPE_IMM32",
356 { "OPERAND_TYPE_IMM32S",
358 { "OPERAND_TYPE_IMM64",
360 { "OPERAND_TYPE_BASEINDEX",
362 { "OPERAND_TYPE_DISP8",
364 { "OPERAND_TYPE_DISP16",
366 { "OPERAND_TYPE_DISP32",
368 { "OPERAND_TYPE_DISP32S",
370 { "OPERAND_TYPE_DISP64",
372 { "OPERAND_TYPE_INOUTPORTREG",
374 { "OPERAND_TYPE_SHIFTCOUNT",
376 { "OPERAND_TYPE_CONTROL",
378 { "OPERAND_TYPE_TEST",
380 { "OPERAND_TYPE_DEBUG",
382 { "OPERAND_TYPE_FLOATREG",
384 { "OPERAND_TYPE_FLOATACC",
386 { "OPERAND_TYPE_SREG2",
388 { "OPERAND_TYPE_SREG3",
390 { "OPERAND_TYPE_ACC",
392 { "OPERAND_TYPE_JUMPABSOLUTE",
394 { "OPERAND_TYPE_REGMMX",
396 { "OPERAND_TYPE_REGXMM",
398 { "OPERAND_TYPE_REGYMM",
400 { "OPERAND_TYPE_REGZMM",
402 { "OPERAND_TYPE_REGMASK",
404 { "OPERAND_TYPE_ESSEG",
406 { "OPERAND_TYPE_ACC32",
408 { "OPERAND_TYPE_ACC64",
410 { "OPERAND_TYPE_INOUTPORTREG",
412 { "OPERAND_TYPE_REG16_INOUTPORTREG",
413 "Reg16|InOutPortReg" },
414 { "OPERAND_TYPE_DISP16_32",
416 { "OPERAND_TYPE_ANYDISP",
417 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
418 { "OPERAND_TYPE_IMM16_32",
420 { "OPERAND_TYPE_IMM16_32S",
422 { "OPERAND_TYPE_IMM16_32_32S",
423 "Imm16|Imm32|Imm32S" },
424 { "OPERAND_TYPE_IMM32_64",
426 { "OPERAND_TYPE_IMM32_32S_DISP32",
427 "Imm32|Imm32S|Disp32" },
428 { "OPERAND_TYPE_IMM64_DISP64",
430 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
431 "Imm32|Imm32S|Imm64|Disp32" },
432 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
433 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
434 { "OPERAND_TYPE_VEC_IMM4",
436 { "OPERAND_TYPE_REGBND",
438 { "OPERAND_TYPE_VEC_DISP8",
442 typedef struct bitfield
449 #define BITFIELD(n) { n, 0, #n }
451 static bitfield cpu_flags
[] =
459 BITFIELD (CpuClflush
),
461 BITFIELD (CpuSYSCALL
),
466 BITFIELD (CpuFISTTP
),
472 BITFIELD (CpuSSE4_1
),
473 BITFIELD (CpuSSE4_2
),
476 BITFIELD (CpuAVX512F
),
477 BITFIELD (CpuAVX512CD
),
478 BITFIELD (CpuAVX512ER
),
479 BITFIELD (CpuAVX512PF
),
480 BITFIELD (CpuAVX512VL
),
481 BITFIELD (CpuAVX512DQ
),
482 BITFIELD (CpuAVX512BW
),
488 BITFIELD (Cpu3dnowA
),
489 BITFIELD (CpuPadLock
),
495 BITFIELD (CpuXsaveopt
),
497 BITFIELD (CpuPCLMUL
),
508 BITFIELD (CpuRdtscp
),
509 BITFIELD (CpuFSGSBase
),
516 BITFIELD (CpuINVPCID
),
517 BITFIELD (CpuVMFUNC
),
518 BITFIELD (CpuRDSEED
),
520 BITFIELD (CpuPRFCHW
),
524 BITFIELD (CpuClflushOpt
),
525 BITFIELD (CpuXSAVES
),
526 BITFIELD (CpuXSAVEC
),
527 BITFIELD (CpuPREFETCHWT1
),
533 BITFIELD (CpuAVX512IFMA
),
534 BITFIELD (CpuAVX512VBMI
),
535 BITFIELD (CpuAVX512_4FMAPS
),
536 BITFIELD (CpuAVX512_4VNNIW
),
537 BITFIELD (CpuAVX512_VPOPCNTDQ
),
538 BITFIELD (CpuAVX512_VBMI2
),
539 BITFIELD (CpuAVX512_VNNI
),
540 BITFIELD (CpuMWAITX
),
541 BITFIELD (CpuCLZERO
),
544 BITFIELD (CpuPTWRITE
),
548 BITFIELD (CpuVPCLMULQDQ
),
549 BITFIELD (CpuRegMMX
),
550 BITFIELD (CpuRegXMM
),
551 BITFIELD (CpuRegYMM
),
552 BITFIELD (CpuRegZMM
),
553 BITFIELD (CpuRegMask
),
555 BITFIELD (CpuUnused
),
559 static bitfield opcode_modifiers
[] =
565 BITFIELD (ShortForm
),
567 BITFIELD (JumpDword
),
569 BITFIELD (JumpInterSegment
),
576 BITFIELD (CheckRegSize
),
577 BITFIELD (IgnoreSize
),
578 BITFIELD (DefaultSize
),
587 BITFIELD (BNDPrefixOk
),
588 BITFIELD (NoTrackPrefixOk
),
589 BITFIELD (IsLockable
),
590 BITFIELD (RegKludge
),
591 BITFIELD (FirstXmm0
),
592 BITFIELD (Implicit1stXmm0
),
593 BITFIELD (RepPrefixOk
),
594 BITFIELD (HLEPrefixOk
),
597 BITFIELD (AddrPrefixOp0
),
606 BITFIELD (VexOpcode
),
607 BITFIELD (VexSources
),
608 BITFIELD (VexImmExt
),
615 BITFIELD (Broadcast
),
616 BITFIELD (StaticRounding
),
618 BITFIELD (Disp8MemShift
),
619 BITFIELD (NoDefMask
),
620 BITFIELD (ImplicitQuadGroup
),
622 BITFIELD (ATTMnemonic
),
623 BITFIELD (ATTSyntax
),
624 BITFIELD (IntelSyntax
),
629 static bitfield operand_types
[] =
648 BITFIELD (BaseIndex
),
654 BITFIELD (InOutPortReg
),
655 BITFIELD (ShiftCount
),
663 BITFIELD (JumpAbsolute
),
676 BITFIELD (Unspecified
),
680 BITFIELD (Vec_Disp8
),
686 static const char *filename
;
689 compare (const void *x
, const void *y
)
691 const bitfield
*xp
= (const bitfield
*) x
;
692 const bitfield
*yp
= (const bitfield
*) y
;
693 return xp
->position
- yp
->position
;
697 fail (const char *message
, ...)
701 va_start (args
, message
);
702 fprintf (stderr
, _("%s: Error: "), program_name
);
703 vfprintf (stderr
, message
, args
);
709 process_copyright (FILE *fp
)
711 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
712 /* Copyright (C) 2007-2017 Free Software Foundation, Inc.\n\
714 This file is part of the GNU opcodes library.\n\
716 This library is free software; you can redistribute it and/or modify\n\
717 it under the terms of the GNU General Public License as published by\n\
718 the Free Software Foundation; either version 3, or (at your option)\n\
719 any later version.\n\
721 It is distributed in the hope that it will be useful, but WITHOUT\n\
722 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
723 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
724 License for more details.\n\
726 You should have received a copy of the GNU General Public License\n\
727 along with this program; if not, write to the Free Software\n\
728 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
729 MA 02110-1301, USA. */\n");
732 /* Remove leading white spaces. */
735 remove_leading_whitespaces (char *str
)
737 while (ISSPACE (*str
))
742 /* Remove trailing white spaces. */
745 remove_trailing_whitespaces (char *str
)
747 size_t last
= strlen (str
);
755 if (ISSPACE (str
[last
]))
763 /* Find next field separated by SEP and terminate it. Return a
764 pointer to the one after it. */
767 next_field (char *str
, char sep
, char **next
, char *last
)
771 p
= remove_leading_whitespaces (str
);
772 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
775 remove_trailing_whitespaces (p
);
785 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
788 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
,
789 int value
, unsigned int size
,
792 char *str
, *next
, *last
;
795 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
796 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
798 /* Turn on selective bits. */
799 char *init
= xstrdup (cpu_flag_init
[i
].init
);
800 last
= init
+ strlen (init
);
801 for (next
= init
; next
&& next
< last
; )
803 str
= next_field (next
, '|', &next
, last
);
805 set_bitfield (str
, array
, 1, size
, lineno
);
815 set_bitfield (char *f
, bitfield
*array
, int value
,
816 unsigned int size
, int lineno
)
820 if (strcmp (f
, "CpuFP") == 0)
822 set_bitfield("Cpu387", array
, value
, size
, lineno
);
823 set_bitfield("Cpu287", array
, value
, size
, lineno
);
826 else if (strcmp (f
, "Mmword") == 0)
828 else if (strcmp (f
, "Oword") == 0)
831 for (i
= 0; i
< size
; i
++)
832 if (strcasecmp (array
[i
].name
, f
) == 0)
834 array
[i
].value
= value
;
840 const char *v
= strchr (f
, '=');
847 for (i
= 0; i
< size
; i
++)
848 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
850 value
= strtol (v
+ 1, &end
, 0);
853 array
[i
].value
= value
;
861 /* Handle CPU_XXX_FLAGS. */
862 if (!set_bitfield_from_cpu_flag_init (f
, array
, value
, size
, lineno
))
866 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
868 fail (_("Unknown bitfield: %s\n"), f
);
872 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
873 int macro
, const char *comma
, const char *indent
)
877 fprintf (table
, "%s{ { ", indent
);
879 for (i
= 0; i
< size
- 1; i
++)
881 if (((i
+ 1) % 20) != 0)
882 fprintf (table
, "%d, ", flags
[i
].value
);
884 fprintf (table
, "%d,", flags
[i
].value
);
885 if (((i
+ 1) % 20) == 0)
887 /* We need \\ for macro. */
889 fprintf (table
, " \\\n %s", indent
);
891 fprintf (table
, "\n %s", indent
);
895 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
899 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
900 const char *comma
, const char *indent
,
903 char *str
, *next
, *last
;
905 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
907 /* Copy the default cpu flags. */
908 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
910 if (strcasecmp (flag
, "unknown") == 0)
912 /* We turn on everything except for cpu64 in case of
913 CPU_UNKNOWN_FLAGS. */
914 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
915 if (flags
[i
].position
!= Cpu64
)
918 else if (flag
[0] == '~')
920 last
= flag
+ strlen (flag
);
927 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
934 /* First we turn on everything except for cpu64. */
935 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
936 if (flags
[i
].position
!= Cpu64
)
939 /* Turn off selective bits. */
940 for (; next
&& next
< last
; )
942 str
= next_field (next
, '|', &next
, last
);
944 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
947 else if (strcmp (flag
, "0"))
949 /* Turn on selective bits. */
950 last
= flag
+ strlen (flag
);
951 for (next
= flag
; next
&& next
< last
; )
953 str
= next_field (next
, '|', &next
, last
);
955 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
959 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
964 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
968 fprintf (table
, " { ");
970 for (i
= 0; i
< size
- 1; i
++)
972 if (((i
+ 1) % 20) != 0)
973 fprintf (table
, "%d, ", modifier
[i
].value
);
975 fprintf (table
, "%d,", modifier
[i
].value
);
976 if (((i
+ 1) % 20) == 0)
977 fprintf (table
, "\n ");
980 fprintf (table
, "%d },\n", modifier
[i
].value
);
984 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
986 char *str
, *next
, *last
;
987 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
989 /* Copy the default opcode modifier. */
990 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
992 if (strcmp (mod
, "0"))
994 last
= mod
+ strlen (mod
);
995 for (next
= mod
; next
&& next
< last
; )
997 str
= next_field (next
, '|', &next
, last
);
999 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
1003 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1007 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
1008 int macro
, const char *indent
)
1012 fprintf (table
, "{ { ");
1014 for (i
= 0; i
< size
- 1; i
++)
1016 if (((i
+ 1) % 20) != 0)
1017 fprintf (table
, "%d, ", types
[i
].value
);
1019 fprintf (table
, "%d,", types
[i
].value
);
1020 if (((i
+ 1) % 20) == 0)
1022 /* We need \\ for macro. */
1024 fprintf (table
, " \\\n%s", indent
);
1026 fprintf (table
, "\n%s", indent
);
1030 fprintf (table
, "%d } }", types
[i
].value
);
1034 process_i386_operand_type (FILE *table
, char *op
, int macro
,
1035 const char *indent
, int lineno
)
1037 char *str
, *next
, *last
;
1038 bitfield types
[ARRAY_SIZE (operand_types
)];
1040 /* Copy the default operand type. */
1041 memcpy (types
, operand_types
, sizeof (types
));
1043 if (strcmp (op
, "0"))
1045 last
= op
+ strlen (op
);
1046 for (next
= op
; next
&& next
< last
; )
1048 str
= next_field (next
, '|', &next
, last
);
1050 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1053 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
1058 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1059 char *last
, int lineno
)
1062 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1063 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1065 /* Find number of operands. */
1066 operands
= next_field (str
, ',', &str
, last
);
1068 /* Find base_opcode. */
1069 base_opcode
= next_field (str
, ',', &str
, last
);
1071 /* Find extension_opcode. */
1072 extension_opcode
= next_field (str
, ',', &str
, last
);
1074 /* Find opcode_length. */
1075 opcode_length
= next_field (str
, ',', &str
, last
);
1077 /* Find cpu_flags. */
1078 cpu_flags
= next_field (str
, ',', &str
, last
);
1080 /* Find opcode_modifier. */
1081 opcode_modifier
= next_field (str
, ',', &str
, last
);
1083 /* Remove the first {. */
1084 str
= remove_leading_whitespaces (str
);
1087 str
= remove_leading_whitespaces (str
+ 1);
1091 /* There are at least "X}". */
1095 /* Remove trailing white spaces and }. */
1099 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1108 /* Find operand_types. */
1109 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1113 operand_types
[i
] = NULL
;
1117 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1118 if (*operand_types
[i
] == '0')
1121 operand_types
[i
] = NULL
;
1126 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1127 name
, operands
, base_opcode
, extension_opcode
,
1130 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1132 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
1134 fprintf (table
, " { ");
1136 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1138 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1141 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
1146 fprintf (table
, ",\n ");
1148 process_i386_operand_type (table
, operand_types
[i
], 0,
1151 fprintf (table
, " } },\n");
1154 struct opcode_hash_entry
1156 struct opcode_hash_entry
*next
;
1162 /* Calculate the hash value of an opcode hash entry P. */
1165 opcode_hash_hash (const void *p
)
1167 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1168 return htab_hash_string (entry
->name
);
1171 /* Compare a string Q against an opcode hash entry P. */
1174 opcode_hash_eq (const void *p
, const void *q
)
1176 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1177 const char *name
= (const char *) q
;
1178 return strcmp (name
, entry
->name
) == 0;
1182 process_i386_opcodes (FILE *table
)
1187 char *str
, *p
, *last
, *name
;
1188 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1189 htab_t opcode_hash_table
;
1190 struct opcode_hash_entry
**opcode_array
;
1191 unsigned int opcode_array_size
= 1024;
1194 filename
= "i386-opc.tbl";
1195 fp
= fopen (filename
, "r");
1198 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1202 opcode_array
= (struct opcode_hash_entry
**)
1203 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1205 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1206 opcode_hash_eq
, NULL
,
1209 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1210 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1212 /* Put everything on opcode array. */
1215 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1220 p
= remove_leading_whitespaces (buf
);
1222 /* Skip comments. */
1223 str
= strstr (p
, "//");
1227 /* Remove trailing white spaces. */
1228 remove_trailing_whitespaces (p
);
1233 /* Ignore comments. */
1241 last
= p
+ strlen (p
);
1244 name
= next_field (p
, ',', &str
, last
);
1246 /* Get the slot in hash table. */
1247 hash_slot
= (struct opcode_hash_entry
**)
1248 htab_find_slot_with_hash (opcode_hash_table
, name
,
1249 htab_hash_string (name
),
1252 if (*hash_slot
== NULL
)
1254 /* It is the new one. Put it on opcode array. */
1255 if (i
>= opcode_array_size
)
1257 /* Grow the opcode array when needed. */
1258 opcode_array_size
+= 1024;
1259 opcode_array
= (struct opcode_hash_entry
**)
1260 xrealloc (opcode_array
,
1261 sizeof (*opcode_array
) * opcode_array_size
);
1264 opcode_array
[i
] = (struct opcode_hash_entry
*)
1265 xmalloc (sizeof (struct opcode_hash_entry
));
1266 opcode_array
[i
]->next
= NULL
;
1267 opcode_array
[i
]->name
= xstrdup (name
);
1268 opcode_array
[i
]->opcode
= xstrdup (str
);
1269 opcode_array
[i
]->lineno
= lineno
;
1270 *hash_slot
= opcode_array
[i
];
1275 /* Append it to the existing one. */
1277 while ((*entry
) != NULL
)
1278 entry
= &(*entry
)->next
;
1279 *entry
= (struct opcode_hash_entry
*)
1280 xmalloc (sizeof (struct opcode_hash_entry
));
1281 (*entry
)->next
= NULL
;
1282 (*entry
)->name
= (*hash_slot
)->name
;
1283 (*entry
)->opcode
= xstrdup (str
);
1284 (*entry
)->lineno
= lineno
;
1288 /* Process opcode array. */
1289 for (j
= 0; j
< i
; j
++)
1291 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1295 lineno
= next
->lineno
;
1296 last
= str
+ strlen (str
);
1297 output_i386_opcode (table
, name
, str
, last
, lineno
);
1303 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1305 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1307 process_i386_opcode_modifier (table
, "0", -1);
1309 fprintf (table
, " { ");
1310 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1311 fprintf (table
, " } }\n");
1313 fprintf (table
, "};\n");
1317 process_i386_registers (FILE *table
)
1321 char *str
, *p
, *last
;
1322 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1323 char *dw2_32_num
, *dw2_64_num
;
1326 filename
= "i386-reg.tbl";
1327 fp
= fopen (filename
, "r");
1329 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1332 fprintf (table
, "\n/* i386 register table. */\n\n");
1333 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1337 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1342 p
= remove_leading_whitespaces (buf
);
1344 /* Skip comments. */
1345 str
= strstr (p
, "//");
1349 /* Remove trailing white spaces. */
1350 remove_trailing_whitespaces (p
);
1355 fprintf (table
, "%s\n", p
);
1363 last
= p
+ strlen (p
);
1365 /* Find reg_name. */
1366 reg_name
= next_field (p
, ',', &str
, last
);
1368 /* Find reg_type. */
1369 reg_type
= next_field (str
, ',', &str
, last
);
1371 /* Find reg_flags. */
1372 reg_flags
= next_field (str
, ',', &str
, last
);
1375 reg_num
= next_field (str
, ',', &str
, last
);
1377 fprintf (table
, " { \"%s\",\n ", reg_name
);
1379 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1381 /* Find 32-bit Dwarf2 register number. */
1382 dw2_32_num
= next_field (str
, ',', &str
, last
);
1384 /* Find 64-bit Dwarf2 register number. */
1385 dw2_64_num
= next_field (str
, ',', &str
, last
);
1387 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1388 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1393 fprintf (table
, "};\n");
1395 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1399 process_i386_initializers (void)
1402 FILE *fp
= fopen ("i386-init.h", "w");
1406 fail (_("can't create i386-init.h, errno = %s\n"),
1409 process_copyright (fp
);
1411 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1413 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1414 init
= xstrdup (cpu_flag_init
[i
].init
);
1415 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1419 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1421 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1422 init
= xstrdup (operand_type_init
[i
].init
);
1423 process_i386_operand_type (fp
, init
, 1, " ", -1);
1431 /* Program options. */
1432 #define OPTION_SRCDIR 200
1434 struct option long_options
[] =
1436 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1437 {"debug", no_argument
, NULL
, 'd'},
1438 {"version", no_argument
, NULL
, 'V'},
1439 {"help", no_argument
, NULL
, 'h'},
1440 {0, no_argument
, NULL
, 0}
1444 print_version (void)
1446 printf ("%s: version 1.0\n", program_name
);
1451 usage (FILE * stream
, int status
)
1453 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1459 main (int argc
, char **argv
)
1461 extern int chdir (char *);
1462 char *srcdir
= NULL
;
1464 unsigned int i
, cpumax
;
1467 program_name
= *argv
;
1468 xmalloc_set_program_name (program_name
);
1470 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1495 if (chdir (srcdir
) != 0)
1496 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1497 srcdir
, xstrerror (errno
));
1499 /* cpu_flags isn't sorted by position. */
1501 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1502 if (cpu_flags
[i
].position
> cpumax
)
1503 cpumax
= cpu_flags
[i
].position
;
1505 /* Check the unused bitfield in i386_cpu_flags. */
1507 if ((cpumax
- 1) != CpuMax
)
1508 fail (_("CpuMax != %d!\n"), cpumax
);
1510 if (cpumax
!= CpuMax
)
1511 fail (_("CpuMax != %d!\n"), cpumax
);
1513 c
= CpuNumOfBits
- CpuMax
- 1;
1515 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1518 /* Check the unused bitfield in i386_operand_type. */
1520 c
= OTNumOfBits
- OTMax
- 1;
1522 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1525 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1528 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1529 sizeof (opcode_modifiers
[0]), compare
);
1531 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1532 sizeof (operand_types
[0]), compare
);
1534 table
= fopen ("i386-tbl.h", "w");
1536 fail (_("can't create i386-tbl.h, errno = %s\n"),
1539 process_copyright (table
);
1541 process_i386_opcodes (table
);
1542 process_i386_registers (table
);
1543 process_i386_initializers ();