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 const initializer operand_type_shorthands
[] =
340 { "Reg8", "Reg|Byte" },
341 { "Reg16", "Reg|Word" },
342 { "Reg32", "Reg|Dword" },
343 { "Reg64", "Reg|Qword" },
344 { "FloatAcc", "Acc|Tbyte" },
345 { "FloatReg", "Reg|Tbyte" },
346 { "RegXMM", "RegSIMD|Xmmword" },
347 { "RegYMM", "RegSIMD|Ymmword" },
348 { "RegZMM", "RegSIMD|Zmmword" },
351 static initializer operand_type_init
[] =
353 { "OPERAND_TYPE_NONE",
355 { "OPERAND_TYPE_REG8",
357 { "OPERAND_TYPE_REG16",
359 { "OPERAND_TYPE_REG32",
361 { "OPERAND_TYPE_REG64",
363 { "OPERAND_TYPE_IMM1",
365 { "OPERAND_TYPE_IMM8",
367 { "OPERAND_TYPE_IMM8S",
369 { "OPERAND_TYPE_IMM16",
371 { "OPERAND_TYPE_IMM32",
373 { "OPERAND_TYPE_IMM32S",
375 { "OPERAND_TYPE_IMM64",
377 { "OPERAND_TYPE_BASEINDEX",
379 { "OPERAND_TYPE_DISP8",
381 { "OPERAND_TYPE_DISP16",
383 { "OPERAND_TYPE_DISP32",
385 { "OPERAND_TYPE_DISP32S",
387 { "OPERAND_TYPE_DISP64",
389 { "OPERAND_TYPE_INOUTPORTREG",
391 { "OPERAND_TYPE_SHIFTCOUNT",
393 { "OPERAND_TYPE_CONTROL",
395 { "OPERAND_TYPE_TEST",
397 { "OPERAND_TYPE_DEBUG",
399 { "OPERAND_TYPE_FLOATREG",
401 { "OPERAND_TYPE_FLOATACC",
403 { "OPERAND_TYPE_SREG2",
405 { "OPERAND_TYPE_SREG3",
407 { "OPERAND_TYPE_ACC",
409 { "OPERAND_TYPE_JUMPABSOLUTE",
411 { "OPERAND_TYPE_REGMMX",
413 { "OPERAND_TYPE_REGXMM",
415 { "OPERAND_TYPE_REGMASK",
417 { "OPERAND_TYPE_ESSEG",
419 { "OPERAND_TYPE_ACC32",
421 { "OPERAND_TYPE_ACC64",
423 { "OPERAND_TYPE_INOUTPORTREG",
425 { "OPERAND_TYPE_REG16_INOUTPORTREG",
426 "Reg16|InOutPortReg" },
427 { "OPERAND_TYPE_DISP16_32",
429 { "OPERAND_TYPE_ANYDISP",
430 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
431 { "OPERAND_TYPE_IMM16_32",
433 { "OPERAND_TYPE_IMM16_32S",
435 { "OPERAND_TYPE_IMM16_32_32S",
436 "Imm16|Imm32|Imm32S" },
437 { "OPERAND_TYPE_IMM32_64",
439 { "OPERAND_TYPE_IMM32_32S_DISP32",
440 "Imm32|Imm32S|Disp32" },
441 { "OPERAND_TYPE_IMM64_DISP64",
443 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
444 "Imm32|Imm32S|Imm64|Disp32" },
445 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
446 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
447 { "OPERAND_TYPE_VEC_IMM4",
449 { "OPERAND_TYPE_REGBND",
453 typedef struct bitfield
460 #define BITFIELD(n) { n, 0, #n }
462 static bitfield cpu_flags
[] =
470 BITFIELD (CpuClflush
),
472 BITFIELD (CpuSYSCALL
),
477 BITFIELD (CpuFISTTP
),
483 BITFIELD (CpuSSE4_1
),
484 BITFIELD (CpuSSE4_2
),
487 BITFIELD (CpuAVX512F
),
488 BITFIELD (CpuAVX512CD
),
489 BITFIELD (CpuAVX512ER
),
490 BITFIELD (CpuAVX512PF
),
491 BITFIELD (CpuAVX512VL
),
492 BITFIELD (CpuAVX512DQ
),
493 BITFIELD (CpuAVX512BW
),
499 BITFIELD (Cpu3dnowA
),
500 BITFIELD (CpuPadLock
),
506 BITFIELD (CpuXsaveopt
),
508 BITFIELD (CpuPCLMUL
),
519 BITFIELD (CpuRdtscp
),
520 BITFIELD (CpuFSGSBase
),
527 BITFIELD (CpuINVPCID
),
528 BITFIELD (CpuVMFUNC
),
529 BITFIELD (CpuRDSEED
),
531 BITFIELD (CpuPRFCHW
),
535 BITFIELD (CpuClflushOpt
),
536 BITFIELD (CpuXSAVES
),
537 BITFIELD (CpuXSAVEC
),
538 BITFIELD (CpuPREFETCHWT1
),
544 BITFIELD (CpuAVX512IFMA
),
545 BITFIELD (CpuAVX512VBMI
),
546 BITFIELD (CpuAVX512_4FMAPS
),
547 BITFIELD (CpuAVX512_4VNNIW
),
548 BITFIELD (CpuAVX512_VPOPCNTDQ
),
549 BITFIELD (CpuAVX512_VBMI2
),
550 BITFIELD (CpuAVX512_VNNI
),
551 BITFIELD (CpuAVX512_BITALG
),
552 BITFIELD (CpuMWAITX
),
553 BITFIELD (CpuCLZERO
),
556 BITFIELD (CpuPTWRITE
),
560 BITFIELD (CpuVPCLMULQDQ
),
561 BITFIELD (CpuRegMMX
),
562 BITFIELD (CpuRegXMM
),
563 BITFIELD (CpuRegYMM
),
564 BITFIELD (CpuRegZMM
),
565 BITFIELD (CpuRegMask
),
567 BITFIELD (CpuUnused
),
571 static bitfield opcode_modifiers
[] =
577 BITFIELD (ShortForm
),
579 BITFIELD (JumpDword
),
581 BITFIELD (JumpInterSegment
),
588 BITFIELD (CheckRegSize
),
589 BITFIELD (IgnoreSize
),
590 BITFIELD (DefaultSize
),
599 BITFIELD (BNDPrefixOk
),
600 BITFIELD (NoTrackPrefixOk
),
601 BITFIELD (IsLockable
),
602 BITFIELD (RegKludge
),
603 BITFIELD (Implicit1stXmm0
),
604 BITFIELD (RepPrefixOk
),
605 BITFIELD (HLEPrefixOk
),
608 BITFIELD (AddrPrefixOp0
),
617 BITFIELD (VexOpcode
),
618 BITFIELD (VexSources
),
619 BITFIELD (VexImmExt
),
626 BITFIELD (Broadcast
),
627 BITFIELD (StaticRounding
),
629 BITFIELD (Disp8MemShift
),
630 BITFIELD (NoDefMask
),
631 BITFIELD (ImplicitQuadGroup
),
633 BITFIELD (ATTMnemonic
),
634 BITFIELD (ATTSyntax
),
635 BITFIELD (IntelSyntax
),
640 static bitfield operand_types
[] =
653 BITFIELD (BaseIndex
),
659 BITFIELD (InOutPortReg
),
660 BITFIELD (ShiftCount
),
667 BITFIELD (JumpAbsolute
),
680 BITFIELD (Unspecified
),
689 static const char *filename
;
690 static i386_cpu_flags active_cpu_flags
;
691 static int active_isstring
;
694 compare (const void *x
, const void *y
)
696 const bitfield
*xp
= (const bitfield
*) x
;
697 const bitfield
*yp
= (const bitfield
*) y
;
698 return xp
->position
- yp
->position
;
702 fail (const char *message
, ...)
706 va_start (args
, message
);
707 fprintf (stderr
, _("%s: Error: "), program_name
);
708 vfprintf (stderr
, message
, args
);
714 process_copyright (FILE *fp
)
716 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
717 /* Copyright (C) 2007-2017 Free Software Foundation, Inc.\n\
719 This file is part of the GNU opcodes library.\n\
721 This library is free software; you can redistribute it and/or modify\n\
722 it under the terms of the GNU General Public License as published by\n\
723 the Free Software Foundation; either version 3, or (at your option)\n\
724 any later version.\n\
726 It is distributed in the hope that it will be useful, but WITHOUT\n\
727 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
728 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
729 License for more details.\n\
731 You should have received a copy of the GNU General Public License\n\
732 along with this program; if not, write to the Free Software\n\
733 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
734 MA 02110-1301, USA. */\n");
737 /* Remove leading white spaces. */
740 remove_leading_whitespaces (char *str
)
742 while (ISSPACE (*str
))
747 /* Remove trailing white spaces. */
750 remove_trailing_whitespaces (char *str
)
752 size_t last
= strlen (str
);
760 if (ISSPACE (str
[last
]))
768 /* Find next field separated by SEP and terminate it. Return a
769 pointer to the one after it. */
772 next_field (char *str
, char sep
, char **next
, char *last
)
776 p
= remove_leading_whitespaces (str
);
777 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
780 remove_trailing_whitespaces (p
);
790 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
793 set_bitfield_from_shorthand (char *f
, bitfield
*array
, 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
);
815 for (i
= 0; i
< ARRAY_SIZE (operand_type_shorthands
); i
++)
816 if (strcmp (operand_type_shorthands
[i
].name
, f
) == 0)
818 /* Turn on selective bits. */
819 char *init
= xstrdup (operand_type_shorthands
[i
].init
);
820 last
= init
+ strlen (init
);
821 for (next
= init
; next
&& next
< last
; )
823 str
= next_field (next
, '|', &next
, last
);
825 set_bitfield (str
, array
, 1, size
, lineno
);
835 set_bitfield (char *f
, bitfield
*array
, int value
,
836 unsigned int size
, int lineno
)
840 if (strcmp (f
, "CpuFP") == 0)
842 set_bitfield("Cpu387", array
, value
, size
, lineno
);
843 set_bitfield("Cpu287", array
, value
, size
, lineno
);
846 else if (strcmp (f
, "Mmword") == 0)
848 else if (strcmp (f
, "Oword") == 0)
851 for (i
= 0; i
< size
; i
++)
852 if (strcasecmp (array
[i
].name
, f
) == 0)
854 array
[i
].value
= value
;
860 const char *v
= strchr (f
, '=');
867 for (i
= 0; i
< size
; i
++)
868 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
870 value
= strtol (v
+ 1, &end
, 0);
873 array
[i
].value
= value
;
881 /* Handle shorthands. */
882 if (value
== 1 && !set_bitfield_from_shorthand (f
, array
, size
, lineno
))
886 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
888 fail (_("Unknown bitfield: %s\n"), f
);
892 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
893 int macro
, const char *comma
, const char *indent
)
897 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
899 fprintf (table
, "%s{ { ", indent
);
901 for (i
= 0; i
< size
- 1; i
++)
903 if (((i
+ 1) % 20) != 0)
904 fprintf (table
, "%d, ", flags
[i
].value
);
906 fprintf (table
, "%d,", flags
[i
].value
);
907 if (((i
+ 1) % 20) == 0)
909 /* We need \\ for macro. */
911 fprintf (table
, " \\\n %s", indent
);
913 fprintf (table
, "\n %s", indent
);
916 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
919 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
923 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
924 const char *comma
, const char *indent
,
927 char *str
, *next
, *last
;
929 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
931 /* Copy the default cpu flags. */
932 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
934 if (strcasecmp (flag
, "unknown") == 0)
936 /* We turn on everything except for cpu64 in case of
937 CPU_UNKNOWN_FLAGS. */
938 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
939 if (flags
[i
].position
!= Cpu64
)
942 else if (flag
[0] == '~')
944 last
= flag
+ strlen (flag
);
951 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
958 /* First we turn on everything except for cpu64. */
959 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
960 if (flags
[i
].position
!= Cpu64
)
963 /* Turn off selective bits. */
964 for (; next
&& next
< last
; )
966 str
= next_field (next
, '|', &next
, last
);
968 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
971 else if (strcmp (flag
, "0"))
973 /* Turn on selective bits. */
974 last
= flag
+ strlen (flag
);
975 for (next
= flag
; next
&& next
< last
; )
977 str
= next_field (next
, '|', &next
, last
);
979 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
983 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
988 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
992 fprintf (table
, " { ");
994 for (i
= 0; i
< size
- 1; i
++)
996 if (((i
+ 1) % 20) != 0)
997 fprintf (table
, "%d, ", modifier
[i
].value
);
999 fprintf (table
, "%d,", modifier
[i
].value
);
1000 if (((i
+ 1) % 20) == 0)
1001 fprintf (table
, "\n ");
1004 fprintf (table
, "%d },\n", modifier
[i
].value
);
1008 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
1010 char *str
, *next
, *last
;
1011 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1013 active_isstring
= 0;
1015 /* Copy the default opcode modifier. */
1016 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1018 if (strcmp (mod
, "0"))
1020 last
= mod
+ strlen (mod
);
1021 for (next
= mod
; next
&& next
< last
; )
1023 str
= next_field (next
, '|', &next
, last
);
1026 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
1028 if (strcasecmp(str
, "IsString") == 0)
1029 active_isstring
= 1;
1033 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1043 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
1044 enum stage stage
, const char *indent
)
1048 fprintf (table
, "{ { ");
1050 for (i
= 0; i
< size
- 1; i
++)
1052 if (((i
+ 1) % 20) != 0)
1053 fprintf (table
, "%d, ", types
[i
].value
);
1055 fprintf (table
, "%d,", types
[i
].value
);
1056 if (((i
+ 1) % 20) == 0)
1058 /* We need \\ for macro. */
1059 if (stage
== stage_macros
)
1060 fprintf (table
, " \\\n%s", indent
);
1062 fprintf (table
, "\n%s", indent
);
1066 fprintf (table
, "%d } }", types
[i
].value
);
1070 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1071 const char *indent
, int lineno
)
1073 char *str
, *next
, *last
;
1074 bitfield types
[ARRAY_SIZE (operand_types
)];
1076 /* Copy the default operand type. */
1077 memcpy (types
, operand_types
, sizeof (types
));
1079 if (strcmp (op
, "0"))
1083 last
= op
+ strlen (op
);
1084 for (next
= op
; next
&& next
< last
; )
1086 str
= next_field (next
, '|', &next
, last
);
1089 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1090 if (strcasecmp(str
, "BaseIndex") == 0)
1095 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1097 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1098 if (!active_cpu_flags
.bitfield
.cpu64
1099 && !active_cpu_flags
.bitfield
.cpumpx
)
1100 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1101 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1102 if (!active_cpu_flags
.bitfield
.cpuno64
)
1103 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1106 output_operand_type (table
, types
, ARRAY_SIZE (types
), stage
,
1111 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1112 char *last
, int lineno
)
1115 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1116 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1118 /* Find number of operands. */
1119 operands
= next_field (str
, ',', &str
, last
);
1121 /* Find base_opcode. */
1122 base_opcode
= next_field (str
, ',', &str
, last
);
1124 /* Find extension_opcode. */
1125 extension_opcode
= next_field (str
, ',', &str
, last
);
1127 /* Find opcode_length. */
1128 opcode_length
= next_field (str
, ',', &str
, last
);
1130 /* Find cpu_flags. */
1131 cpu_flags
= next_field (str
, ',', &str
, last
);
1133 /* Find opcode_modifier. */
1134 opcode_modifier
= next_field (str
, ',', &str
, last
);
1136 /* Remove the first {. */
1137 str
= remove_leading_whitespaces (str
);
1140 str
= remove_leading_whitespaces (str
+ 1);
1144 /* There are at least "X}". */
1148 /* Remove trailing white spaces and }. */
1152 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1161 /* Find operand_types. */
1162 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1166 operand_types
[i
] = NULL
;
1170 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1171 if (*operand_types
[i
] == '0')
1174 operand_types
[i
] = NULL
;
1179 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1180 name
, operands
, base_opcode
, extension_opcode
,
1183 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1185 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
1187 fprintf (table
, " { ");
1189 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1191 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1194 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1200 fprintf (table
, ",\n ");
1202 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1205 fprintf (table
, " } },\n");
1208 struct opcode_hash_entry
1210 struct opcode_hash_entry
*next
;
1216 /* Calculate the hash value of an opcode hash entry P. */
1219 opcode_hash_hash (const void *p
)
1221 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1222 return htab_hash_string (entry
->name
);
1225 /* Compare a string Q against an opcode hash entry P. */
1228 opcode_hash_eq (const void *p
, const void *q
)
1230 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1231 const char *name
= (const char *) q
;
1232 return strcmp (name
, entry
->name
) == 0;
1236 process_i386_opcodes (FILE *table
)
1241 char *str
, *p
, *last
, *name
;
1242 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1243 htab_t opcode_hash_table
;
1244 struct opcode_hash_entry
**opcode_array
;
1245 unsigned int opcode_array_size
= 1024;
1248 filename
= "i386-opc.tbl";
1249 fp
= fopen (filename
, "r");
1252 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1256 opcode_array
= (struct opcode_hash_entry
**)
1257 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1259 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1260 opcode_hash_eq
, NULL
,
1263 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1264 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1266 /* Put everything on opcode array. */
1269 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1274 p
= remove_leading_whitespaces (buf
);
1276 /* Skip comments. */
1277 str
= strstr (p
, "//");
1281 /* Remove trailing white spaces. */
1282 remove_trailing_whitespaces (p
);
1287 /* Ignore comments. */
1295 last
= p
+ strlen (p
);
1298 name
= next_field (p
, ',', &str
, last
);
1300 /* Get the slot in hash table. */
1301 hash_slot
= (struct opcode_hash_entry
**)
1302 htab_find_slot_with_hash (opcode_hash_table
, name
,
1303 htab_hash_string (name
),
1306 if (*hash_slot
== NULL
)
1308 /* It is the new one. Put it on opcode array. */
1309 if (i
>= opcode_array_size
)
1311 /* Grow the opcode array when needed. */
1312 opcode_array_size
+= 1024;
1313 opcode_array
= (struct opcode_hash_entry
**)
1314 xrealloc (opcode_array
,
1315 sizeof (*opcode_array
) * opcode_array_size
);
1318 opcode_array
[i
] = (struct opcode_hash_entry
*)
1319 xmalloc (sizeof (struct opcode_hash_entry
));
1320 opcode_array
[i
]->next
= NULL
;
1321 opcode_array
[i
]->name
= xstrdup (name
);
1322 opcode_array
[i
]->opcode
= xstrdup (str
);
1323 opcode_array
[i
]->lineno
= lineno
;
1324 *hash_slot
= opcode_array
[i
];
1329 /* Append it to the existing one. */
1331 while ((*entry
) != NULL
)
1332 entry
= &(*entry
)->next
;
1333 *entry
= (struct opcode_hash_entry
*)
1334 xmalloc (sizeof (struct opcode_hash_entry
));
1335 (*entry
)->next
= NULL
;
1336 (*entry
)->name
= (*hash_slot
)->name
;
1337 (*entry
)->opcode
= xstrdup (str
);
1338 (*entry
)->lineno
= lineno
;
1342 /* Process opcode array. */
1343 for (j
= 0; j
< i
; j
++)
1345 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1349 lineno
= next
->lineno
;
1350 last
= str
+ strlen (str
);
1351 output_i386_opcode (table
, name
, str
, last
, lineno
);
1357 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1359 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1361 process_i386_opcode_modifier (table
, "0", -1);
1363 fprintf (table
, " { ");
1364 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1365 fprintf (table
, " } }\n");
1367 fprintf (table
, "};\n");
1371 process_i386_registers (FILE *table
)
1375 char *str
, *p
, *last
;
1376 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1377 char *dw2_32_num
, *dw2_64_num
;
1380 filename
= "i386-reg.tbl";
1381 fp
= fopen (filename
, "r");
1383 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1386 fprintf (table
, "\n/* i386 register table. */\n\n");
1387 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1391 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1396 p
= remove_leading_whitespaces (buf
);
1398 /* Skip comments. */
1399 str
= strstr (p
, "//");
1403 /* Remove trailing white spaces. */
1404 remove_trailing_whitespaces (p
);
1409 fprintf (table
, "%s\n", p
);
1417 last
= p
+ strlen (p
);
1419 /* Find reg_name. */
1420 reg_name
= next_field (p
, ',', &str
, last
);
1422 /* Find reg_type. */
1423 reg_type
= next_field (str
, ',', &str
, last
);
1425 /* Find reg_flags. */
1426 reg_flags
= next_field (str
, ',', &str
, last
);
1429 reg_num
= next_field (str
, ',', &str
, last
);
1431 fprintf (table
, " { \"%s\",\n ", reg_name
);
1433 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1436 /* Find 32-bit Dwarf2 register number. */
1437 dw2_32_num
= next_field (str
, ',', &str
, last
);
1439 /* Find 64-bit Dwarf2 register number. */
1440 dw2_64_num
= next_field (str
, ',', &str
, last
);
1442 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1443 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1448 fprintf (table
, "};\n");
1450 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1454 process_i386_initializers (void)
1457 FILE *fp
= fopen ("i386-init.h", "w");
1461 fail (_("can't create i386-init.h, errno = %s\n"),
1464 process_copyright (fp
);
1466 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1468 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1469 init
= xstrdup (cpu_flag_init
[i
].init
);
1470 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1474 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1476 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1477 init
= xstrdup (operand_type_init
[i
].init
);
1478 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1486 /* Program options. */
1487 #define OPTION_SRCDIR 200
1489 struct option long_options
[] =
1491 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1492 {"debug", no_argument
, NULL
, 'd'},
1493 {"version", no_argument
, NULL
, 'V'},
1494 {"help", no_argument
, NULL
, 'h'},
1495 {0, no_argument
, NULL
, 0}
1499 print_version (void)
1501 printf ("%s: version 1.0\n", program_name
);
1506 usage (FILE * stream
, int status
)
1508 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1514 main (int argc
, char **argv
)
1516 extern int chdir (char *);
1517 char *srcdir
= NULL
;
1519 unsigned int i
, cpumax
;
1522 program_name
= *argv
;
1523 xmalloc_set_program_name (program_name
);
1525 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1550 if (chdir (srcdir
) != 0)
1551 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1552 srcdir
, xstrerror (errno
));
1554 /* cpu_flags isn't sorted by position. */
1556 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1557 if (cpu_flags
[i
].position
> cpumax
)
1558 cpumax
= cpu_flags
[i
].position
;
1560 /* Check the unused bitfield in i386_cpu_flags. */
1562 if ((cpumax
- 1) != CpuMax
)
1563 fail (_("CpuMax != %d!\n"), cpumax
);
1565 if (cpumax
!= CpuMax
)
1566 fail (_("CpuMax != %d!\n"), cpumax
);
1568 c
= CpuNumOfBits
- CpuMax
- 1;
1570 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1573 /* Check the unused bitfield in i386_operand_type. */
1575 c
= OTNumOfBits
- OTMax
- 1;
1577 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1580 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1583 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1584 sizeof (opcode_modifiers
[0]), compare
);
1586 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1587 sizeof (operand_types
[0]), compare
);
1589 table
= fopen ("i386-tbl.h", "w");
1591 fail (_("can't create i386-tbl.h, errno = %s\n"),
1594 process_copyright (table
);
1596 process_i386_opcodes (table
);
1597 process_i386_registers (table
);
1598 process_i386_initializers ();