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" },
346 static initializer operand_type_init
[] =
348 { "OPERAND_TYPE_NONE",
350 { "OPERAND_TYPE_REG8",
352 { "OPERAND_TYPE_REG16",
354 { "OPERAND_TYPE_REG32",
356 { "OPERAND_TYPE_REG64",
358 { "OPERAND_TYPE_IMM1",
360 { "OPERAND_TYPE_IMM8",
362 { "OPERAND_TYPE_IMM8S",
364 { "OPERAND_TYPE_IMM16",
366 { "OPERAND_TYPE_IMM32",
368 { "OPERAND_TYPE_IMM32S",
370 { "OPERAND_TYPE_IMM64",
372 { "OPERAND_TYPE_BASEINDEX",
374 { "OPERAND_TYPE_DISP8",
376 { "OPERAND_TYPE_DISP16",
378 { "OPERAND_TYPE_DISP32",
380 { "OPERAND_TYPE_DISP32S",
382 { "OPERAND_TYPE_DISP64",
384 { "OPERAND_TYPE_INOUTPORTREG",
386 { "OPERAND_TYPE_SHIFTCOUNT",
388 { "OPERAND_TYPE_CONTROL",
390 { "OPERAND_TYPE_TEST",
392 { "OPERAND_TYPE_DEBUG",
394 { "OPERAND_TYPE_FLOATREG",
396 { "OPERAND_TYPE_FLOATACC",
398 { "OPERAND_TYPE_SREG2",
400 { "OPERAND_TYPE_SREG3",
402 { "OPERAND_TYPE_ACC",
404 { "OPERAND_TYPE_JUMPABSOLUTE",
406 { "OPERAND_TYPE_REGMMX",
408 { "OPERAND_TYPE_REGXMM",
410 { "OPERAND_TYPE_REGYMM",
412 { "OPERAND_TYPE_REGZMM",
414 { "OPERAND_TYPE_REGMASK",
416 { "OPERAND_TYPE_ESSEG",
418 { "OPERAND_TYPE_ACC32",
420 { "OPERAND_TYPE_ACC64",
422 { "OPERAND_TYPE_INOUTPORTREG",
424 { "OPERAND_TYPE_REG16_INOUTPORTREG",
425 "Reg16|InOutPortReg" },
426 { "OPERAND_TYPE_DISP16_32",
428 { "OPERAND_TYPE_ANYDISP",
429 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
430 { "OPERAND_TYPE_IMM16_32",
432 { "OPERAND_TYPE_IMM16_32S",
434 { "OPERAND_TYPE_IMM16_32_32S",
435 "Imm16|Imm32|Imm32S" },
436 { "OPERAND_TYPE_IMM32_64",
438 { "OPERAND_TYPE_IMM32_32S_DISP32",
439 "Imm32|Imm32S|Disp32" },
440 { "OPERAND_TYPE_IMM64_DISP64",
442 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
443 "Imm32|Imm32S|Imm64|Disp32" },
444 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
445 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
446 { "OPERAND_TYPE_VEC_IMM4",
448 { "OPERAND_TYPE_REGBND",
452 typedef struct bitfield
459 #define BITFIELD(n) { n, 0, #n }
461 static bitfield cpu_flags
[] =
469 BITFIELD (CpuClflush
),
471 BITFIELD (CpuSYSCALL
),
476 BITFIELD (CpuFISTTP
),
482 BITFIELD (CpuSSE4_1
),
483 BITFIELD (CpuSSE4_2
),
486 BITFIELD (CpuAVX512F
),
487 BITFIELD (CpuAVX512CD
),
488 BITFIELD (CpuAVX512ER
),
489 BITFIELD (CpuAVX512PF
),
490 BITFIELD (CpuAVX512VL
),
491 BITFIELD (CpuAVX512DQ
),
492 BITFIELD (CpuAVX512BW
),
498 BITFIELD (Cpu3dnowA
),
499 BITFIELD (CpuPadLock
),
505 BITFIELD (CpuXsaveopt
),
507 BITFIELD (CpuPCLMUL
),
518 BITFIELD (CpuRdtscp
),
519 BITFIELD (CpuFSGSBase
),
526 BITFIELD (CpuINVPCID
),
527 BITFIELD (CpuVMFUNC
),
528 BITFIELD (CpuRDSEED
),
530 BITFIELD (CpuPRFCHW
),
534 BITFIELD (CpuClflushOpt
),
535 BITFIELD (CpuXSAVES
),
536 BITFIELD (CpuXSAVEC
),
537 BITFIELD (CpuPREFETCHWT1
),
543 BITFIELD (CpuAVX512IFMA
),
544 BITFIELD (CpuAVX512VBMI
),
545 BITFIELD (CpuAVX512_4FMAPS
),
546 BITFIELD (CpuAVX512_4VNNIW
),
547 BITFIELD (CpuAVX512_VPOPCNTDQ
),
548 BITFIELD (CpuAVX512_VBMI2
),
549 BITFIELD (CpuAVX512_VNNI
),
550 BITFIELD (CpuAVX512_BITALG
),
551 BITFIELD (CpuMWAITX
),
552 BITFIELD (CpuCLZERO
),
555 BITFIELD (CpuPTWRITE
),
559 BITFIELD (CpuVPCLMULQDQ
),
560 BITFIELD (CpuRegMMX
),
561 BITFIELD (CpuRegXMM
),
562 BITFIELD (CpuRegYMM
),
563 BITFIELD (CpuRegZMM
),
564 BITFIELD (CpuRegMask
),
566 BITFIELD (CpuUnused
),
570 static bitfield opcode_modifiers
[] =
576 BITFIELD (ShortForm
),
578 BITFIELD (JumpDword
),
580 BITFIELD (JumpInterSegment
),
587 BITFIELD (CheckRegSize
),
588 BITFIELD (IgnoreSize
),
589 BITFIELD (DefaultSize
),
598 BITFIELD (BNDPrefixOk
),
599 BITFIELD (NoTrackPrefixOk
),
600 BITFIELD (IsLockable
),
601 BITFIELD (RegKludge
),
602 BITFIELD (FirstXmm0
),
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
[] =
656 BITFIELD (BaseIndex
),
662 BITFIELD (InOutPortReg
),
663 BITFIELD (ShiftCount
),
671 BITFIELD (JumpAbsolute
),
684 BITFIELD (Unspecified
),
693 static const char *filename
;
694 static i386_cpu_flags active_cpu_flags
;
695 static int active_isstring
;
698 compare (const void *x
, const void *y
)
700 const bitfield
*xp
= (const bitfield
*) x
;
701 const bitfield
*yp
= (const bitfield
*) y
;
702 return xp
->position
- yp
->position
;
706 fail (const char *message
, ...)
710 va_start (args
, message
);
711 fprintf (stderr
, _("%s: Error: "), program_name
);
712 vfprintf (stderr
, message
, args
);
718 process_copyright (FILE *fp
)
720 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
721 /* Copyright (C) 2007-2017 Free Software Foundation, Inc.\n\
723 This file is part of the GNU opcodes library.\n\
725 This library is free software; you can redistribute it and/or modify\n\
726 it under the terms of the GNU General Public License as published by\n\
727 the Free Software Foundation; either version 3, or (at your option)\n\
728 any later version.\n\
730 It is distributed in the hope that it will be useful, but WITHOUT\n\
731 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
732 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
733 License for more details.\n\
735 You should have received a copy of the GNU General Public License\n\
736 along with this program; if not, write to the Free Software\n\
737 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
738 MA 02110-1301, USA. */\n");
741 /* Remove leading white spaces. */
744 remove_leading_whitespaces (char *str
)
746 while (ISSPACE (*str
))
751 /* Remove trailing white spaces. */
754 remove_trailing_whitespaces (char *str
)
756 size_t last
= strlen (str
);
764 if (ISSPACE (str
[last
]))
772 /* Find next field separated by SEP and terminate it. Return a
773 pointer to the one after it. */
776 next_field (char *str
, char sep
, char **next
, char *last
)
780 p
= remove_leading_whitespaces (str
);
781 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
784 remove_trailing_whitespaces (p
);
794 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
797 set_bitfield_from_shorthand (char *f
, bitfield
*array
, unsigned int size
,
800 char *str
, *next
, *last
;
803 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
804 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
806 /* Turn on selective bits. */
807 char *init
= xstrdup (cpu_flag_init
[i
].init
);
808 last
= init
+ strlen (init
);
809 for (next
= init
; next
&& next
< last
; )
811 str
= next_field (next
, '|', &next
, last
);
813 set_bitfield (str
, array
, 1, size
, lineno
);
819 for (i
= 0; i
< ARRAY_SIZE (operand_type_shorthands
); i
++)
820 if (strcmp (operand_type_shorthands
[i
].name
, f
) == 0)
822 /* Turn on selective bits. */
823 char *init
= xstrdup (operand_type_shorthands
[i
].init
);
824 last
= init
+ strlen (init
);
825 for (next
= init
; next
&& next
< last
; )
827 str
= next_field (next
, '|', &next
, last
);
829 set_bitfield (str
, array
, 1, size
, lineno
);
839 set_bitfield (char *f
, bitfield
*array
, int value
,
840 unsigned int size
, int lineno
)
844 if (strcmp (f
, "CpuFP") == 0)
846 set_bitfield("Cpu387", array
, value
, size
, lineno
);
847 set_bitfield("Cpu287", array
, value
, size
, lineno
);
850 else if (strcmp (f
, "Mmword") == 0)
852 else if (strcmp (f
, "Oword") == 0)
855 for (i
= 0; i
< size
; i
++)
856 if (strcasecmp (array
[i
].name
, f
) == 0)
858 array
[i
].value
= value
;
864 const char *v
= strchr (f
, '=');
871 for (i
= 0; i
< size
; i
++)
872 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
874 value
= strtol (v
+ 1, &end
, 0);
877 array
[i
].value
= value
;
885 /* Handle shorthands. */
886 if (value
== 1 && !set_bitfield_from_shorthand (f
, array
, size
, lineno
))
890 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
892 fail (_("Unknown bitfield: %s\n"), f
);
896 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
897 int macro
, const char *comma
, const char *indent
)
901 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
903 fprintf (table
, "%s{ { ", indent
);
905 for (i
= 0; i
< size
- 1; i
++)
907 if (((i
+ 1) % 20) != 0)
908 fprintf (table
, "%d, ", flags
[i
].value
);
910 fprintf (table
, "%d,", flags
[i
].value
);
911 if (((i
+ 1) % 20) == 0)
913 /* We need \\ for macro. */
915 fprintf (table
, " \\\n %s", indent
);
917 fprintf (table
, "\n %s", indent
);
920 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
923 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
927 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
928 const char *comma
, const char *indent
,
931 char *str
, *next
, *last
;
933 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
935 /* Copy the default cpu flags. */
936 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
938 if (strcasecmp (flag
, "unknown") == 0)
940 /* We turn on everything except for cpu64 in case of
941 CPU_UNKNOWN_FLAGS. */
942 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
943 if (flags
[i
].position
!= Cpu64
)
946 else if (flag
[0] == '~')
948 last
= flag
+ strlen (flag
);
955 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
962 /* First we turn on everything except for cpu64. */
963 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
964 if (flags
[i
].position
!= Cpu64
)
967 /* Turn off selective bits. */
968 for (; next
&& next
< last
; )
970 str
= next_field (next
, '|', &next
, last
);
972 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
975 else if (strcmp (flag
, "0"))
977 /* Turn on selective bits. */
978 last
= flag
+ strlen (flag
);
979 for (next
= flag
; next
&& next
< last
; )
981 str
= next_field (next
, '|', &next
, last
);
983 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
987 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
992 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
996 fprintf (table
, " { ");
998 for (i
= 0; i
< size
- 1; i
++)
1000 if (((i
+ 1) % 20) != 0)
1001 fprintf (table
, "%d, ", modifier
[i
].value
);
1003 fprintf (table
, "%d,", modifier
[i
].value
);
1004 if (((i
+ 1) % 20) == 0)
1005 fprintf (table
, "\n ");
1008 fprintf (table
, "%d },\n", modifier
[i
].value
);
1012 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
1014 char *str
, *next
, *last
;
1015 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1017 active_isstring
= 0;
1019 /* Copy the default opcode modifier. */
1020 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1022 if (strcmp (mod
, "0"))
1024 last
= mod
+ strlen (mod
);
1025 for (next
= mod
; next
&& next
< last
; )
1027 str
= next_field (next
, '|', &next
, last
);
1030 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
1032 if (strcasecmp(str
, "IsString") == 0)
1033 active_isstring
= 1;
1037 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1047 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
1048 enum stage stage
, const char *indent
)
1052 fprintf (table
, "{ { ");
1054 for (i
= 0; i
< size
- 1; i
++)
1056 if (((i
+ 1) % 20) != 0)
1057 fprintf (table
, "%d, ", types
[i
].value
);
1059 fprintf (table
, "%d,", types
[i
].value
);
1060 if (((i
+ 1) % 20) == 0)
1062 /* We need \\ for macro. */
1063 if (stage
== stage_macros
)
1064 fprintf (table
, " \\\n%s", indent
);
1066 fprintf (table
, "\n%s", indent
);
1070 fprintf (table
, "%d } }", types
[i
].value
);
1074 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1075 const char *indent
, int lineno
)
1077 char *str
, *next
, *last
;
1078 bitfield types
[ARRAY_SIZE (operand_types
)];
1080 /* Copy the default operand type. */
1081 memcpy (types
, operand_types
, sizeof (types
));
1083 if (strcmp (op
, "0"))
1087 last
= op
+ strlen (op
);
1088 for (next
= op
; next
&& next
< last
; )
1090 str
= next_field (next
, '|', &next
, last
);
1093 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1094 if (strcasecmp(str
, "BaseIndex") == 0)
1099 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1101 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1102 if (!active_cpu_flags
.bitfield
.cpu64
1103 && !active_cpu_flags
.bitfield
.cpumpx
)
1104 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1105 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1106 if (!active_cpu_flags
.bitfield
.cpuno64
)
1107 set_bitfield("Disp32S", types
, 1, ARRAY_SIZE (types
), lineno
);
1110 output_operand_type (table
, types
, ARRAY_SIZE (types
), stage
,
1115 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1116 char *last
, int lineno
)
1119 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1120 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1122 /* Find number of operands. */
1123 operands
= next_field (str
, ',', &str
, last
);
1125 /* Find base_opcode. */
1126 base_opcode
= next_field (str
, ',', &str
, last
);
1128 /* Find extension_opcode. */
1129 extension_opcode
= next_field (str
, ',', &str
, last
);
1131 /* Find opcode_length. */
1132 opcode_length
= next_field (str
, ',', &str
, last
);
1134 /* Find cpu_flags. */
1135 cpu_flags
= next_field (str
, ',', &str
, last
);
1137 /* Find opcode_modifier. */
1138 opcode_modifier
= next_field (str
, ',', &str
, last
);
1140 /* Remove the first {. */
1141 str
= remove_leading_whitespaces (str
);
1144 str
= remove_leading_whitespaces (str
+ 1);
1148 /* There are at least "X}". */
1152 /* Remove trailing white spaces and }. */
1156 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1165 /* Find operand_types. */
1166 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1170 operand_types
[i
] = NULL
;
1174 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1175 if (*operand_types
[i
] == '0')
1178 operand_types
[i
] = NULL
;
1183 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1184 name
, operands
, base_opcode
, extension_opcode
,
1187 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1189 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
1191 fprintf (table
, " { ");
1193 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1195 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1198 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1204 fprintf (table
, ",\n ");
1206 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1209 fprintf (table
, " } },\n");
1212 struct opcode_hash_entry
1214 struct opcode_hash_entry
*next
;
1220 /* Calculate the hash value of an opcode hash entry P. */
1223 opcode_hash_hash (const void *p
)
1225 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1226 return htab_hash_string (entry
->name
);
1229 /* Compare a string Q against an opcode hash entry P. */
1232 opcode_hash_eq (const void *p
, const void *q
)
1234 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1235 const char *name
= (const char *) q
;
1236 return strcmp (name
, entry
->name
) == 0;
1240 process_i386_opcodes (FILE *table
)
1245 char *str
, *p
, *last
, *name
;
1246 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1247 htab_t opcode_hash_table
;
1248 struct opcode_hash_entry
**opcode_array
;
1249 unsigned int opcode_array_size
= 1024;
1252 filename
= "i386-opc.tbl";
1253 fp
= fopen (filename
, "r");
1256 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1260 opcode_array
= (struct opcode_hash_entry
**)
1261 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1263 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1264 opcode_hash_eq
, NULL
,
1267 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1268 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1270 /* Put everything on opcode array. */
1273 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1278 p
= remove_leading_whitespaces (buf
);
1280 /* Skip comments. */
1281 str
= strstr (p
, "//");
1285 /* Remove trailing white spaces. */
1286 remove_trailing_whitespaces (p
);
1291 /* Ignore comments. */
1299 last
= p
+ strlen (p
);
1302 name
= next_field (p
, ',', &str
, last
);
1304 /* Get the slot in hash table. */
1305 hash_slot
= (struct opcode_hash_entry
**)
1306 htab_find_slot_with_hash (opcode_hash_table
, name
,
1307 htab_hash_string (name
),
1310 if (*hash_slot
== NULL
)
1312 /* It is the new one. Put it on opcode array. */
1313 if (i
>= opcode_array_size
)
1315 /* Grow the opcode array when needed. */
1316 opcode_array_size
+= 1024;
1317 opcode_array
= (struct opcode_hash_entry
**)
1318 xrealloc (opcode_array
,
1319 sizeof (*opcode_array
) * opcode_array_size
);
1322 opcode_array
[i
] = (struct opcode_hash_entry
*)
1323 xmalloc (sizeof (struct opcode_hash_entry
));
1324 opcode_array
[i
]->next
= NULL
;
1325 opcode_array
[i
]->name
= xstrdup (name
);
1326 opcode_array
[i
]->opcode
= xstrdup (str
);
1327 opcode_array
[i
]->lineno
= lineno
;
1328 *hash_slot
= opcode_array
[i
];
1333 /* Append it to the existing one. */
1335 while ((*entry
) != NULL
)
1336 entry
= &(*entry
)->next
;
1337 *entry
= (struct opcode_hash_entry
*)
1338 xmalloc (sizeof (struct opcode_hash_entry
));
1339 (*entry
)->next
= NULL
;
1340 (*entry
)->name
= (*hash_slot
)->name
;
1341 (*entry
)->opcode
= xstrdup (str
);
1342 (*entry
)->lineno
= lineno
;
1346 /* Process opcode array. */
1347 for (j
= 0; j
< i
; j
++)
1349 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1353 lineno
= next
->lineno
;
1354 last
= str
+ strlen (str
);
1355 output_i386_opcode (table
, name
, str
, last
, lineno
);
1361 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1363 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1365 process_i386_opcode_modifier (table
, "0", -1);
1367 fprintf (table
, " { ");
1368 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1369 fprintf (table
, " } }\n");
1371 fprintf (table
, "};\n");
1375 process_i386_registers (FILE *table
)
1379 char *str
, *p
, *last
;
1380 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1381 char *dw2_32_num
, *dw2_64_num
;
1384 filename
= "i386-reg.tbl";
1385 fp
= fopen (filename
, "r");
1387 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1390 fprintf (table
, "\n/* i386 register table. */\n\n");
1391 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1395 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1400 p
= remove_leading_whitespaces (buf
);
1402 /* Skip comments. */
1403 str
= strstr (p
, "//");
1407 /* Remove trailing white spaces. */
1408 remove_trailing_whitespaces (p
);
1413 fprintf (table
, "%s\n", p
);
1421 last
= p
+ strlen (p
);
1423 /* Find reg_name. */
1424 reg_name
= next_field (p
, ',', &str
, last
);
1426 /* Find reg_type. */
1427 reg_type
= next_field (str
, ',', &str
, last
);
1429 /* Find reg_flags. */
1430 reg_flags
= next_field (str
, ',', &str
, last
);
1433 reg_num
= next_field (str
, ',', &str
, last
);
1435 fprintf (table
, " { \"%s\",\n ", reg_name
);
1437 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1440 /* Find 32-bit Dwarf2 register number. */
1441 dw2_32_num
= next_field (str
, ',', &str
, last
);
1443 /* Find 64-bit Dwarf2 register number. */
1444 dw2_64_num
= next_field (str
, ',', &str
, last
);
1446 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1447 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1452 fprintf (table
, "};\n");
1454 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1458 process_i386_initializers (void)
1461 FILE *fp
= fopen ("i386-init.h", "w");
1465 fail (_("can't create i386-init.h, errno = %s\n"),
1468 process_copyright (fp
);
1470 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1472 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1473 init
= xstrdup (cpu_flag_init
[i
].init
);
1474 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1478 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1480 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1481 init
= xstrdup (operand_type_init
[i
].init
);
1482 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
1490 /* Program options. */
1491 #define OPTION_SRCDIR 200
1493 struct option long_options
[] =
1495 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1496 {"debug", no_argument
, NULL
, 'd'},
1497 {"version", no_argument
, NULL
, 'V'},
1498 {"help", no_argument
, NULL
, 'h'},
1499 {0, no_argument
, NULL
, 0}
1503 print_version (void)
1505 printf ("%s: version 1.0\n", program_name
);
1510 usage (FILE * stream
, int status
)
1512 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1518 main (int argc
, char **argv
)
1520 extern int chdir (char *);
1521 char *srcdir
= NULL
;
1523 unsigned int i
, cpumax
;
1526 program_name
= *argv
;
1527 xmalloc_set_program_name (program_name
);
1529 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1554 if (chdir (srcdir
) != 0)
1555 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1556 srcdir
, xstrerror (errno
));
1558 /* cpu_flags isn't sorted by position. */
1560 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1561 if (cpu_flags
[i
].position
> cpumax
)
1562 cpumax
= cpu_flags
[i
].position
;
1564 /* Check the unused bitfield in i386_cpu_flags. */
1566 if ((cpumax
- 1) != CpuMax
)
1567 fail (_("CpuMax != %d!\n"), cpumax
);
1569 if (cpumax
!= CpuMax
)
1570 fail (_("CpuMax != %d!\n"), cpumax
);
1572 c
= CpuNumOfBits
- CpuMax
- 1;
1574 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1577 /* Check the unused bitfield in i386_operand_type. */
1579 c
= OTNumOfBits
- OTMax
- 1;
1581 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1584 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1587 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1588 sizeof (opcode_modifiers
[0]), compare
);
1590 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1591 sizeof (operand_types
[0]), compare
);
1593 table
= fopen ("i386-tbl.h", "w");
1595 fail (_("can't create i386-tbl.h, errno = %s\n"),
1598 process_copyright (table
);
1600 process_i386_opcodes (table
);
1601 process_i386_registers (table
);
1602 process_i386_initializers ();