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" },
230 { "CPU_AVX512_BITALG_FLAGS",
231 "CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
237 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
240 { "CPU_RDSEED_FLAGS",
242 { "CPU_PRFCHW_FLAGS",
249 "CPU_SSE2_FLAGS|CpuSHA" },
250 { "CPU_CLFLUSHOPT_FLAGS",
252 { "CPU_XSAVES_FLAGS",
253 "CPU_XSAVE_FLAGS|CpuXSAVES" },
254 { "CPU_XSAVEC_FLAGS",
255 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
256 { "CPU_PREFETCHWT1_FLAGS",
262 { "CPU_CLZERO_FLAGS",
264 { "CPU_MWAITX_FLAGS",
270 { "CPU_PTWRITE_FLAGS",
278 { "CPU_VPCLMULQDQ_FLAGS",
280 { "CPU_ANY_X87_FLAGS",
281 "CPU_ANY_287_FLAGS|Cpu8087" },
282 { "CPU_ANY_287_FLAGS",
283 "CPU_ANY_387_FLAGS|Cpu287" },
284 { "CPU_ANY_387_FLAGS",
285 "CPU_ANY_687_FLAGS|Cpu387" },
286 { "CPU_ANY_687_FLAGS",
287 "Cpu687|CpuFISTTP" },
288 { "CPU_ANY_MMX_FLAGS",
289 "CPU_3DNOWA_FLAGS" },
290 { "CPU_ANY_SSE_FLAGS",
291 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
292 { "CPU_ANY_SSE2_FLAGS",
293 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
294 { "CPU_ANY_SSE3_FLAGS",
295 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
296 { "CPU_ANY_SSSE3_FLAGS",
297 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
298 { "CPU_ANY_SSE4_1_FLAGS",
299 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
300 { "CPU_ANY_SSE4_2_FLAGS",
302 { "CPU_ANY_AVX_FLAGS",
303 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
304 { "CPU_ANY_AVX2_FLAGS",
306 { "CPU_ANY_AVX512F_FLAGS",
307 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512F" },
308 { "CPU_ANY_AVX512CD_FLAGS",
310 { "CPU_ANY_AVX512ER_FLAGS",
312 { "CPU_ANY_AVX512PF_FLAGS",
314 { "CPU_ANY_AVX512DQ_FLAGS",
316 { "CPU_ANY_AVX512BW_FLAGS",
318 { "CPU_ANY_AVX512VL_FLAGS",
320 { "CPU_ANY_AVX512IFMA_FLAGS",
322 { "CPU_ANY_AVX512VBMI_FLAGS",
324 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
325 "CpuAVX512_4FMAPS" },
326 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
327 "CpuAVX512_4VNNIW" },
328 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
329 "CpuAVX512_VPOPCNTDQ" },
330 { "CPU_ANY_AVX512_VBMI2_FLAGS",
332 { "CPU_ANY_AVX512_VNNI_FLAGS",
334 { "CPU_ANY_AVX512_BITALG_FLAGS",
335 "CpuAVX512_BITALG" },
338 static initializer operand_type_init
[] =
340 { "OPERAND_TYPE_NONE",
342 { "OPERAND_TYPE_REG8",
344 { "OPERAND_TYPE_REG16",
346 { "OPERAND_TYPE_REG32",
348 { "OPERAND_TYPE_REG64",
350 { "OPERAND_TYPE_IMM1",
352 { "OPERAND_TYPE_IMM8",
354 { "OPERAND_TYPE_IMM8S",
356 { "OPERAND_TYPE_IMM16",
358 { "OPERAND_TYPE_IMM32",
360 { "OPERAND_TYPE_IMM32S",
362 { "OPERAND_TYPE_IMM64",
364 { "OPERAND_TYPE_BASEINDEX",
366 { "OPERAND_TYPE_DISP8",
368 { "OPERAND_TYPE_DISP16",
370 { "OPERAND_TYPE_DISP32",
372 { "OPERAND_TYPE_DISP32S",
374 { "OPERAND_TYPE_DISP64",
376 { "OPERAND_TYPE_INOUTPORTREG",
378 { "OPERAND_TYPE_SHIFTCOUNT",
380 { "OPERAND_TYPE_CONTROL",
382 { "OPERAND_TYPE_TEST",
384 { "OPERAND_TYPE_DEBUG",
386 { "OPERAND_TYPE_FLOATREG",
388 { "OPERAND_TYPE_FLOATACC",
390 { "OPERAND_TYPE_SREG2",
392 { "OPERAND_TYPE_SREG3",
394 { "OPERAND_TYPE_ACC",
396 { "OPERAND_TYPE_JUMPABSOLUTE",
398 { "OPERAND_TYPE_REGMMX",
400 { "OPERAND_TYPE_REGXMM",
402 { "OPERAND_TYPE_REGYMM",
404 { "OPERAND_TYPE_REGZMM",
406 { "OPERAND_TYPE_REGMASK",
408 { "OPERAND_TYPE_ESSEG",
410 { "OPERAND_TYPE_ACC32",
412 { "OPERAND_TYPE_ACC64",
414 { "OPERAND_TYPE_INOUTPORTREG",
416 { "OPERAND_TYPE_REG16_INOUTPORTREG",
417 "Reg16|InOutPortReg" },
418 { "OPERAND_TYPE_DISP16_32",
420 { "OPERAND_TYPE_ANYDISP",
421 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
422 { "OPERAND_TYPE_IMM16_32",
424 { "OPERAND_TYPE_IMM16_32S",
426 { "OPERAND_TYPE_IMM16_32_32S",
427 "Imm16|Imm32|Imm32S" },
428 { "OPERAND_TYPE_IMM32_64",
430 { "OPERAND_TYPE_IMM32_32S_DISP32",
431 "Imm32|Imm32S|Disp32" },
432 { "OPERAND_TYPE_IMM64_DISP64",
434 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
435 "Imm32|Imm32S|Imm64|Disp32" },
436 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
437 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
438 { "OPERAND_TYPE_VEC_IMM4",
440 { "OPERAND_TYPE_REGBND",
444 typedef struct bitfield
451 #define BITFIELD(n) { n, 0, #n }
453 static bitfield cpu_flags
[] =
461 BITFIELD (CpuClflush
),
463 BITFIELD (CpuSYSCALL
),
468 BITFIELD (CpuFISTTP
),
474 BITFIELD (CpuSSE4_1
),
475 BITFIELD (CpuSSE4_2
),
478 BITFIELD (CpuAVX512F
),
479 BITFIELD (CpuAVX512CD
),
480 BITFIELD (CpuAVX512ER
),
481 BITFIELD (CpuAVX512PF
),
482 BITFIELD (CpuAVX512VL
),
483 BITFIELD (CpuAVX512DQ
),
484 BITFIELD (CpuAVX512BW
),
490 BITFIELD (Cpu3dnowA
),
491 BITFIELD (CpuPadLock
),
497 BITFIELD (CpuXsaveopt
),
499 BITFIELD (CpuPCLMUL
),
510 BITFIELD (CpuRdtscp
),
511 BITFIELD (CpuFSGSBase
),
518 BITFIELD (CpuINVPCID
),
519 BITFIELD (CpuVMFUNC
),
520 BITFIELD (CpuRDSEED
),
522 BITFIELD (CpuPRFCHW
),
526 BITFIELD (CpuClflushOpt
),
527 BITFIELD (CpuXSAVES
),
528 BITFIELD (CpuXSAVEC
),
529 BITFIELD (CpuPREFETCHWT1
),
535 BITFIELD (CpuAVX512IFMA
),
536 BITFIELD (CpuAVX512VBMI
),
537 BITFIELD (CpuAVX512_4FMAPS
),
538 BITFIELD (CpuAVX512_4VNNIW
),
539 BITFIELD (CpuAVX512_VPOPCNTDQ
),
540 BITFIELD (CpuAVX512_VBMI2
),
541 BITFIELD (CpuAVX512_VNNI
),
542 BITFIELD (CpuAVX512_BITALG
),
543 BITFIELD (CpuMWAITX
),
544 BITFIELD (CpuCLZERO
),
547 BITFIELD (CpuPTWRITE
),
551 BITFIELD (CpuVPCLMULQDQ
),
552 BITFIELD (CpuRegMMX
),
553 BITFIELD (CpuRegXMM
),
554 BITFIELD (CpuRegYMM
),
555 BITFIELD (CpuRegZMM
),
556 BITFIELD (CpuRegMask
),
558 BITFIELD (CpuUnused
),
562 static bitfield opcode_modifiers
[] =
568 BITFIELD (ShortForm
),
570 BITFIELD (JumpDword
),
572 BITFIELD (JumpInterSegment
),
579 BITFIELD (CheckRegSize
),
580 BITFIELD (IgnoreSize
),
581 BITFIELD (DefaultSize
),
590 BITFIELD (BNDPrefixOk
),
591 BITFIELD (NoTrackPrefixOk
),
592 BITFIELD (IsLockable
),
593 BITFIELD (RegKludge
),
594 BITFIELD (FirstXmm0
),
595 BITFIELD (Implicit1stXmm0
),
596 BITFIELD (RepPrefixOk
),
597 BITFIELD (HLEPrefixOk
),
600 BITFIELD (AddrPrefixOp0
),
609 BITFIELD (VexOpcode
),
610 BITFIELD (VexSources
),
611 BITFIELD (VexImmExt
),
618 BITFIELD (Broadcast
),
619 BITFIELD (StaticRounding
),
621 BITFIELD (Disp8MemShift
),
622 BITFIELD (NoDefMask
),
623 BITFIELD (ImplicitQuadGroup
),
625 BITFIELD (ATTMnemonic
),
626 BITFIELD (ATTSyntax
),
627 BITFIELD (IntelSyntax
),
632 static bitfield operand_types
[] =
651 BITFIELD (BaseIndex
),
657 BITFIELD (InOutPortReg
),
658 BITFIELD (ShiftCount
),
666 BITFIELD (JumpAbsolute
),
679 BITFIELD (Unspecified
),
688 static const char *filename
;
689 static i386_cpu_flags active_cpu_flags
;
690 static int active_isstring
;
693 compare (const void *x
, const void *y
)
695 const bitfield
*xp
= (const bitfield
*) x
;
696 const bitfield
*yp
= (const bitfield
*) y
;
697 return xp
->position
- yp
->position
;
701 fail (const char *message
, ...)
705 va_start (args
, message
);
706 fprintf (stderr
, _("%s: Error: "), program_name
);
707 vfprintf (stderr
, message
, args
);
713 process_copyright (FILE *fp
)
715 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
716 /* Copyright (C) 2007-2017 Free Software Foundation, Inc.\n\
718 This file is part of the GNU opcodes library.\n\
720 This library is free software; you can redistribute it and/or modify\n\
721 it under the terms of the GNU General Public License as published by\n\
722 the Free Software Foundation; either version 3, or (at your option)\n\
723 any later version.\n\
725 It is distributed in the hope that it will be useful, but WITHOUT\n\
726 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
727 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
728 License for more details.\n\
730 You should have received a copy of the GNU General Public License\n\
731 along with this program; if not, write to the Free Software\n\
732 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
733 MA 02110-1301, USA. */\n");
736 /* Remove leading white spaces. */
739 remove_leading_whitespaces (char *str
)
741 while (ISSPACE (*str
))
746 /* Remove trailing white spaces. */
749 remove_trailing_whitespaces (char *str
)
751 size_t last
= strlen (str
);
759 if (ISSPACE (str
[last
]))
767 /* Find next field separated by SEP and terminate it. Return a
768 pointer to the one after it. */
771 next_field (char *str
, char sep
, char **next
, char *last
)
775 p
= remove_leading_whitespaces (str
);
776 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
779 remove_trailing_whitespaces (p
);
789 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
792 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
,
793 int value
, unsigned int size
,
796 char *str
, *next
, *last
;
799 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
800 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
802 /* Turn on selective bits. */
803 char *init
= xstrdup (cpu_flag_init
[i
].init
);
804 last
= init
+ strlen (init
);
805 for (next
= init
; next
&& next
< last
; )
807 str
= next_field (next
, '|', &next
, last
);
809 set_bitfield (str
, array
, 1, size
, lineno
);
819 set_bitfield (char *f
, bitfield
*array
, int value
,
820 unsigned int size
, int lineno
)
824 if (strcmp (f
, "CpuFP") == 0)
826 set_bitfield("Cpu387", array
, value
, size
, lineno
);
827 set_bitfield("Cpu287", array
, value
, size
, lineno
);
830 else if (strcmp (f
, "Mmword") == 0)
832 else if (strcmp (f
, "Oword") == 0)
835 for (i
= 0; i
< size
; i
++)
836 if (strcasecmp (array
[i
].name
, f
) == 0)
838 array
[i
].value
= value
;
844 const char *v
= strchr (f
, '=');
851 for (i
= 0; i
< size
; i
++)
852 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
854 value
= strtol (v
+ 1, &end
, 0);
857 array
[i
].value
= value
;
865 /* Handle CPU_XXX_FLAGS. */
866 if (!set_bitfield_from_cpu_flag_init (f
, array
, value
, size
, lineno
))
870 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
872 fail (_("Unknown bitfield: %s\n"), f
);
876 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
877 int macro
, const char *comma
, const char *indent
)
881 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
883 fprintf (table
, "%s{ { ", indent
);
885 for (i
= 0; i
< size
- 1; i
++)
887 if (((i
+ 1) % 20) != 0)
888 fprintf (table
, "%d, ", flags
[i
].value
);
890 fprintf (table
, "%d,", flags
[i
].value
);
891 if (((i
+ 1) % 20) == 0)
893 /* We need \\ for macro. */
895 fprintf (table
, " \\\n %s", indent
);
897 fprintf (table
, "\n %s", indent
);
900 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
903 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
907 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
908 const char *comma
, const char *indent
,
911 char *str
, *next
, *last
;
913 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
915 /* Copy the default cpu flags. */
916 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
918 if (strcasecmp (flag
, "unknown") == 0)
920 /* We turn on everything except for cpu64 in case of
921 CPU_UNKNOWN_FLAGS. */
922 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
923 if (flags
[i
].position
!= Cpu64
)
926 else if (flag
[0] == '~')
928 last
= flag
+ strlen (flag
);
935 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
942 /* First we turn on everything except for cpu64. */
943 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
944 if (flags
[i
].position
!= Cpu64
)
947 /* Turn off selective bits. */
948 for (; next
&& next
< last
; )
950 str
= next_field (next
, '|', &next
, last
);
952 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
955 else if (strcmp (flag
, "0"))
957 /* Turn on selective bits. */
958 last
= flag
+ strlen (flag
);
959 for (next
= flag
; next
&& next
< last
; )
961 str
= next_field (next
, '|', &next
, last
);
963 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
967 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
972 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
976 fprintf (table
, " { ");
978 for (i
= 0; i
< size
- 1; i
++)
980 if (((i
+ 1) % 20) != 0)
981 fprintf (table
, "%d, ", modifier
[i
].value
);
983 fprintf (table
, "%d,", modifier
[i
].value
);
984 if (((i
+ 1) % 20) == 0)
985 fprintf (table
, "\n ");
988 fprintf (table
, "%d },\n", modifier
[i
].value
);
992 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
994 char *str
, *next
, *last
;
995 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
999 /* Copy the default opcode modifier. */
1000 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1002 if (strcmp (mod
, "0"))
1004 last
= mod
+ strlen (mod
);
1005 for (next
= mod
; next
&& next
< last
; )
1007 str
= next_field (next
, '|', &next
, last
);
1010 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
1012 if (strcasecmp(str
, "IsString") == 0)
1013 active_isstring
= 1;
1017 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1027 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
1028 enum stage stage
, const char *indent
)
1032 fprintf (table
, "{ { ");
1034 for (i
= 0; i
< size
- 1; i
++)
1036 if (((i
+ 1) % 20) != 0)
1037 fprintf (table
, "%d, ", types
[i
].value
);
1039 fprintf (table
, "%d,", types
[i
].value
);
1040 if (((i
+ 1) % 20) == 0)
1042 /* We need \\ for macro. */
1043 if (stage
== stage_macros
)
1044 fprintf (table
, " \\\n%s", indent
);
1046 fprintf (table
, "\n%s", indent
);
1050 fprintf (table
, "%d } }", types
[i
].value
);
1054 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1055 const char *indent
, int lineno
)
1057 char *str
, *next
, *last
;
1058 bitfield types
[ARRAY_SIZE (operand_types
)];
1060 /* Copy the default operand type. */
1061 memcpy (types
, operand_types
, sizeof (types
));
1063 if (strcmp (op
, "0"))
1067 last
= op
+ strlen (op
);
1068 for (next
= op
; next
&& next
< last
; )
1070 str
= next_field (next
, '|', &next
, last
);
1073 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1074 if (strcasecmp(str
, "BaseIndex") == 0)
1079 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1081 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1082 if (!active_cpu_flags
.bitfield
.cpu64
1083 && !active_cpu_flags
.bitfield
.cpumpx
)
1084 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1085 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1086 if (!active_cpu_flags
.bitfield
.cpuno64
)
1087 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1090 output_operand_type (table
, types
, ARRAY_SIZE (types
), stage
,
1095 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1096 char *last
, int lineno
)
1099 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1100 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1102 /* Find number of operands. */
1103 operands
= next_field (str
, ',', &str
, last
);
1105 /* Find base_opcode. */
1106 base_opcode
= next_field (str
, ',', &str
, last
);
1108 /* Find extension_opcode. */
1109 extension_opcode
= next_field (str
, ',', &str
, last
);
1111 /* Find opcode_length. */
1112 opcode_length
= next_field (str
, ',', &str
, last
);
1114 /* Find cpu_flags. */
1115 cpu_flags
= next_field (str
, ',', &str
, last
);
1117 /* Find opcode_modifier. */
1118 opcode_modifier
= next_field (str
, ',', &str
, last
);
1120 /* Remove the first {. */
1121 str
= remove_leading_whitespaces (str
);
1124 str
= remove_leading_whitespaces (str
+ 1);
1128 /* There are at least "X}". */
1132 /* Remove trailing white spaces and }. */
1136 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1145 /* Find operand_types. */
1146 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1150 operand_types
[i
] = NULL
;
1154 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1155 if (*operand_types
[i
] == '0')
1158 operand_types
[i
] = NULL
;
1163 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1164 name
, operands
, base_opcode
, extension_opcode
,
1167 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1169 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
1171 fprintf (table
, " { ");
1173 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1175 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1178 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1184 fprintf (table
, ",\n ");
1186 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1189 fprintf (table
, " } },\n");
1192 struct opcode_hash_entry
1194 struct opcode_hash_entry
*next
;
1200 /* Calculate the hash value of an opcode hash entry P. */
1203 opcode_hash_hash (const void *p
)
1205 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1206 return htab_hash_string (entry
->name
);
1209 /* Compare a string Q against an opcode hash entry P. */
1212 opcode_hash_eq (const void *p
, const void *q
)
1214 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1215 const char *name
= (const char *) q
;
1216 return strcmp (name
, entry
->name
) == 0;
1220 process_i386_opcodes (FILE *table
)
1225 char *str
, *p
, *last
, *name
;
1226 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1227 htab_t opcode_hash_table
;
1228 struct opcode_hash_entry
**opcode_array
;
1229 unsigned int opcode_array_size
= 1024;
1232 filename
= "i386-opc.tbl";
1233 fp
= fopen (filename
, "r");
1236 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1240 opcode_array
= (struct opcode_hash_entry
**)
1241 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1243 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1244 opcode_hash_eq
, NULL
,
1247 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1248 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1250 /* Put everything on opcode array. */
1253 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1258 p
= remove_leading_whitespaces (buf
);
1260 /* Skip comments. */
1261 str
= strstr (p
, "//");
1265 /* Remove trailing white spaces. */
1266 remove_trailing_whitespaces (p
);
1271 /* Ignore comments. */
1279 last
= p
+ strlen (p
);
1282 name
= next_field (p
, ',', &str
, last
);
1284 /* Get the slot in hash table. */
1285 hash_slot
= (struct opcode_hash_entry
**)
1286 htab_find_slot_with_hash (opcode_hash_table
, name
,
1287 htab_hash_string (name
),
1290 if (*hash_slot
== NULL
)
1292 /* It is the new one. Put it on opcode array. */
1293 if (i
>= opcode_array_size
)
1295 /* Grow the opcode array when needed. */
1296 opcode_array_size
+= 1024;
1297 opcode_array
= (struct opcode_hash_entry
**)
1298 xrealloc (opcode_array
,
1299 sizeof (*opcode_array
) * opcode_array_size
);
1302 opcode_array
[i
] = (struct opcode_hash_entry
*)
1303 xmalloc (sizeof (struct opcode_hash_entry
));
1304 opcode_array
[i
]->next
= NULL
;
1305 opcode_array
[i
]->name
= xstrdup (name
);
1306 opcode_array
[i
]->opcode
= xstrdup (str
);
1307 opcode_array
[i
]->lineno
= lineno
;
1308 *hash_slot
= opcode_array
[i
];
1313 /* Append it to the existing one. */
1315 while ((*entry
) != NULL
)
1316 entry
= &(*entry
)->next
;
1317 *entry
= (struct opcode_hash_entry
*)
1318 xmalloc (sizeof (struct opcode_hash_entry
));
1319 (*entry
)->next
= NULL
;
1320 (*entry
)->name
= (*hash_slot
)->name
;
1321 (*entry
)->opcode
= xstrdup (str
);
1322 (*entry
)->lineno
= lineno
;
1326 /* Process opcode array. */
1327 for (j
= 0; j
< i
; j
++)
1329 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1333 lineno
= next
->lineno
;
1334 last
= str
+ strlen (str
);
1335 output_i386_opcode (table
, name
, str
, last
, lineno
);
1341 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1343 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1345 process_i386_opcode_modifier (table
, "0", -1);
1347 fprintf (table
, " { ");
1348 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1349 fprintf (table
, " } }\n");
1351 fprintf (table
, "};\n");
1355 process_i386_registers (FILE *table
)
1359 char *str
, *p
, *last
;
1360 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1361 char *dw2_32_num
, *dw2_64_num
;
1364 filename
= "i386-reg.tbl";
1365 fp
= fopen (filename
, "r");
1367 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1370 fprintf (table
, "\n/* i386 register table. */\n\n");
1371 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1375 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1380 p
= remove_leading_whitespaces (buf
);
1382 /* Skip comments. */
1383 str
= strstr (p
, "//");
1387 /* Remove trailing white spaces. */
1388 remove_trailing_whitespaces (p
);
1393 fprintf (table
, "%s\n", p
);
1401 last
= p
+ strlen (p
);
1403 /* Find reg_name. */
1404 reg_name
= next_field (p
, ',', &str
, last
);
1406 /* Find reg_type. */
1407 reg_type
= next_field (str
, ',', &str
, last
);
1409 /* Find reg_flags. */
1410 reg_flags
= next_field (str
, ',', &str
, last
);
1413 reg_num
= next_field (str
, ',', &str
, last
);
1415 fprintf (table
, " { \"%s\",\n ", reg_name
);
1417 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1420 /* Find 32-bit Dwarf2 register number. */
1421 dw2_32_num
= next_field (str
, ',', &str
, last
);
1423 /* Find 64-bit Dwarf2 register number. */
1424 dw2_64_num
= next_field (str
, ',', &str
, last
);
1426 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1427 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1432 fprintf (table
, "};\n");
1434 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1438 process_i386_initializers (void)
1441 FILE *fp
= fopen ("i386-init.h", "w");
1445 fail (_("can't create i386-init.h, errno = %s\n"),
1448 process_copyright (fp
);
1450 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1452 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1453 init
= xstrdup (cpu_flag_init
[i
].init
);
1454 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1458 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1460 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1461 init
= xstrdup (operand_type_init
[i
].init
);
1462 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1470 /* Program options. */
1471 #define OPTION_SRCDIR 200
1473 struct option long_options
[] =
1475 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1476 {"debug", no_argument
, NULL
, 'd'},
1477 {"version", no_argument
, NULL
, 'V'},
1478 {"help", no_argument
, NULL
, 'h'},
1479 {0, no_argument
, NULL
, 0}
1483 print_version (void)
1485 printf ("%s: version 1.0\n", program_name
);
1490 usage (FILE * stream
, int status
)
1492 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1498 main (int argc
, char **argv
)
1500 extern int chdir (char *);
1501 char *srcdir
= NULL
;
1503 unsigned int i
, cpumax
;
1506 program_name
= *argv
;
1507 xmalloc_set_program_name (program_name
);
1509 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1534 if (chdir (srcdir
) != 0)
1535 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1536 srcdir
, xstrerror (errno
));
1538 /* cpu_flags isn't sorted by position. */
1540 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1541 if (cpu_flags
[i
].position
> cpumax
)
1542 cpumax
= cpu_flags
[i
].position
;
1544 /* Check the unused bitfield in i386_cpu_flags. */
1546 if ((cpumax
- 1) != CpuMax
)
1547 fail (_("CpuMax != %d!\n"), cpumax
);
1549 if (cpumax
!= CpuMax
)
1550 fail (_("CpuMax != %d!\n"), cpumax
);
1552 c
= CpuNumOfBits
- CpuMax
- 1;
1554 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1557 /* Check the unused bitfield in i386_operand_type. */
1559 c
= OTNumOfBits
- OTMax
- 1;
1561 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1564 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1567 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1568 sizeof (opcode_modifiers
[0]), compare
);
1570 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1571 sizeof (operand_types
[0]), compare
);
1573 table
= fopen ("i386-tbl.h", "w");
1575 fail (_("can't create i386-tbl.h, errno = %s\n"),
1578 process_copyright (table
);
1580 process_i386_opcodes (table
);
1581 process_i386_registers (table
);
1582 process_i386_initializers ();