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" },
231 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
234 { "CPU_RDSEED_FLAGS",
236 { "CPU_PRFCHW_FLAGS",
243 "CPU_SSE2_FLAGS|CpuSHA" },
244 { "CPU_CLFLUSHOPT_FLAGS",
246 { "CPU_XSAVES_FLAGS",
247 "CPU_XSAVE_FLAGS|CpuXSAVES" },
248 { "CPU_XSAVEC_FLAGS",
249 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
250 { "CPU_PREFETCHWT1_FLAGS",
256 { "CPU_CLZERO_FLAGS",
258 { "CPU_MWAITX_FLAGS",
264 { "CPU_PTWRITE_FLAGS",
268 { "CPU_ANY_X87_FLAGS",
269 "CPU_ANY_287_FLAGS|Cpu8087" },
270 { "CPU_ANY_287_FLAGS",
271 "CPU_ANY_387_FLAGS|Cpu287" },
272 { "CPU_ANY_387_FLAGS",
273 "CPU_ANY_687_FLAGS|Cpu387" },
274 { "CPU_ANY_687_FLAGS",
275 "Cpu687|CpuFISTTP" },
276 { "CPU_ANY_MMX_FLAGS",
277 "CPU_3DNOWA_FLAGS" },
278 { "CPU_ANY_SSE_FLAGS",
279 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
280 { "CPU_ANY_SSE2_FLAGS",
281 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
282 { "CPU_ANY_SSE3_FLAGS",
283 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
284 { "CPU_ANY_SSSE3_FLAGS",
285 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
286 { "CPU_ANY_SSE4_1_FLAGS",
287 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
288 { "CPU_ANY_SSE4_2_FLAGS",
290 { "CPU_ANY_AVX_FLAGS",
291 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
292 { "CPU_ANY_AVX2_FLAGS",
294 { "CPU_ANY_AVX512F_FLAGS",
295 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512F" },
296 { "CPU_ANY_AVX512CD_FLAGS",
298 { "CPU_ANY_AVX512ER_FLAGS",
300 { "CPU_ANY_AVX512PF_FLAGS",
302 { "CPU_ANY_AVX512DQ_FLAGS",
304 { "CPU_ANY_AVX512BW_FLAGS",
306 { "CPU_ANY_AVX512VL_FLAGS",
308 { "CPU_ANY_AVX512IFMA_FLAGS",
310 { "CPU_ANY_AVX512VBMI_FLAGS",
312 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
313 "CpuAVX512_4FMAPS" },
314 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
315 "CpuAVX512_4VNNIW" },
316 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
317 "CpuAVX512_VPOPCNTDQ" },
320 static initializer operand_type_init
[] =
322 { "OPERAND_TYPE_NONE",
324 { "OPERAND_TYPE_REG8",
326 { "OPERAND_TYPE_REG16",
328 { "OPERAND_TYPE_REG32",
330 { "OPERAND_TYPE_REG64",
332 { "OPERAND_TYPE_IMM1",
334 { "OPERAND_TYPE_IMM8",
336 { "OPERAND_TYPE_IMM8S",
338 { "OPERAND_TYPE_IMM16",
340 { "OPERAND_TYPE_IMM32",
342 { "OPERAND_TYPE_IMM32S",
344 { "OPERAND_TYPE_IMM64",
346 { "OPERAND_TYPE_BASEINDEX",
348 { "OPERAND_TYPE_DISP8",
350 { "OPERAND_TYPE_DISP16",
352 { "OPERAND_TYPE_DISP32",
354 { "OPERAND_TYPE_DISP32S",
356 { "OPERAND_TYPE_DISP64",
358 { "OPERAND_TYPE_INOUTPORTREG",
360 { "OPERAND_TYPE_SHIFTCOUNT",
362 { "OPERAND_TYPE_CONTROL",
364 { "OPERAND_TYPE_TEST",
366 { "OPERAND_TYPE_DEBUG",
368 { "OPERAND_TYPE_FLOATREG",
370 { "OPERAND_TYPE_FLOATACC",
372 { "OPERAND_TYPE_SREG2",
374 { "OPERAND_TYPE_SREG3",
376 { "OPERAND_TYPE_ACC",
378 { "OPERAND_TYPE_JUMPABSOLUTE",
380 { "OPERAND_TYPE_REGMMX",
382 { "OPERAND_TYPE_REGXMM",
384 { "OPERAND_TYPE_REGYMM",
386 { "OPERAND_TYPE_REGZMM",
388 { "OPERAND_TYPE_REGMASK",
390 { "OPERAND_TYPE_ESSEG",
392 { "OPERAND_TYPE_ACC32",
394 { "OPERAND_TYPE_ACC64",
396 { "OPERAND_TYPE_INOUTPORTREG",
398 { "OPERAND_TYPE_REG16_INOUTPORTREG",
399 "Reg16|InOutPortReg" },
400 { "OPERAND_TYPE_DISP16_32",
402 { "OPERAND_TYPE_ANYDISP",
403 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
404 { "OPERAND_TYPE_IMM16_32",
406 { "OPERAND_TYPE_IMM16_32S",
408 { "OPERAND_TYPE_IMM16_32_32S",
409 "Imm16|Imm32|Imm32S" },
410 { "OPERAND_TYPE_IMM32_64",
412 { "OPERAND_TYPE_IMM32_32S_DISP32",
413 "Imm32|Imm32S|Disp32" },
414 { "OPERAND_TYPE_IMM64_DISP64",
416 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
417 "Imm32|Imm32S|Imm64|Disp32" },
418 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
419 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
420 { "OPERAND_TYPE_VEC_IMM4",
422 { "OPERAND_TYPE_REGBND",
424 { "OPERAND_TYPE_VEC_DISP8",
428 typedef struct bitfield
435 #define BITFIELD(n) { n, 0, #n }
437 static bitfield cpu_flags
[] =
445 BITFIELD (CpuClflush
),
447 BITFIELD (CpuSYSCALL
),
452 BITFIELD (CpuFISTTP
),
458 BITFIELD (CpuSSE4_1
),
459 BITFIELD (CpuSSE4_2
),
462 BITFIELD (CpuAVX512F
),
463 BITFIELD (CpuAVX512CD
),
464 BITFIELD (CpuAVX512ER
),
465 BITFIELD (CpuAVX512PF
),
466 BITFIELD (CpuAVX512VL
),
467 BITFIELD (CpuAVX512DQ
),
468 BITFIELD (CpuAVX512BW
),
474 BITFIELD (Cpu3dnowA
),
475 BITFIELD (CpuPadLock
),
481 BITFIELD (CpuXsaveopt
),
483 BITFIELD (CpuPCLMUL
),
494 BITFIELD (CpuRdtscp
),
495 BITFIELD (CpuFSGSBase
),
502 BITFIELD (CpuINVPCID
),
503 BITFIELD (CpuVMFUNC
),
504 BITFIELD (CpuRDSEED
),
506 BITFIELD (CpuPRFCHW
),
510 BITFIELD (CpuClflushOpt
),
511 BITFIELD (CpuXSAVES
),
512 BITFIELD (CpuXSAVEC
),
513 BITFIELD (CpuPREFETCHWT1
),
519 BITFIELD (CpuAVX512IFMA
),
520 BITFIELD (CpuAVX512VBMI
),
521 BITFIELD (CpuAVX512_4FMAPS
),
522 BITFIELD (CpuAVX512_4VNNIW
),
523 BITFIELD (CpuAVX512_VPOPCNTDQ
),
524 BITFIELD (CpuMWAITX
),
525 BITFIELD (CpuCLZERO
),
528 BITFIELD (CpuPTWRITE
),
530 BITFIELD (CpuRegMMX
),
531 BITFIELD (CpuRegXMM
),
532 BITFIELD (CpuRegYMM
),
533 BITFIELD (CpuRegZMM
),
534 BITFIELD (CpuRegMask
),
536 BITFIELD (CpuUnused
),
540 static bitfield opcode_modifiers
[] =
546 BITFIELD (ShortForm
),
548 BITFIELD (JumpDword
),
550 BITFIELD (JumpInterSegment
),
557 BITFIELD (CheckRegSize
),
558 BITFIELD (IgnoreSize
),
559 BITFIELD (DefaultSize
),
568 BITFIELD (BNDPrefixOk
),
569 BITFIELD (NoTrackPrefixOk
),
570 BITFIELD (IsLockable
),
571 BITFIELD (RegKludge
),
572 BITFIELD (FirstXmm0
),
573 BITFIELD (Implicit1stXmm0
),
574 BITFIELD (RepPrefixOk
),
575 BITFIELD (HLEPrefixOk
),
578 BITFIELD (AddrPrefixOp0
),
587 BITFIELD (VexOpcode
),
588 BITFIELD (VexSources
),
589 BITFIELD (VexImmExt
),
596 BITFIELD (Broadcast
),
597 BITFIELD (StaticRounding
),
599 BITFIELD (Disp8MemShift
),
600 BITFIELD (NoDefMask
),
601 BITFIELD (ImplicitQuadGroup
),
603 BITFIELD (ATTMnemonic
),
604 BITFIELD (ATTSyntax
),
605 BITFIELD (IntelSyntax
),
610 static bitfield operand_types
[] =
629 BITFIELD (BaseIndex
),
635 BITFIELD (InOutPortReg
),
636 BITFIELD (ShiftCount
),
644 BITFIELD (JumpAbsolute
),
657 BITFIELD (Unspecified
),
661 BITFIELD (Vec_Disp8
),
667 static const char *filename
;
670 compare (const void *x
, const void *y
)
672 const bitfield
*xp
= (const bitfield
*) x
;
673 const bitfield
*yp
= (const bitfield
*) y
;
674 return xp
->position
- yp
->position
;
678 fail (const char *message
, ...)
682 va_start (args
, message
);
683 fprintf (stderr
, _("%s: Error: "), program_name
);
684 vfprintf (stderr
, message
, args
);
690 process_copyright (FILE *fp
)
692 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
693 /* Copyright (C) 2007-2017 Free Software Foundation, Inc.\n\
695 This file is part of the GNU opcodes library.\n\
697 This library is free software; you can redistribute it and/or modify\n\
698 it under the terms of the GNU General Public License as published by\n\
699 the Free Software Foundation; either version 3, or (at your option)\n\
700 any later version.\n\
702 It is distributed in the hope that it will be useful, but WITHOUT\n\
703 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
704 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
705 License for more details.\n\
707 You should have received a copy of the GNU General Public License\n\
708 along with this program; if not, write to the Free Software\n\
709 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
710 MA 02110-1301, USA. */\n");
713 /* Remove leading white spaces. */
716 remove_leading_whitespaces (char *str
)
718 while (ISSPACE (*str
))
723 /* Remove trailing white spaces. */
726 remove_trailing_whitespaces (char *str
)
728 size_t last
= strlen (str
);
736 if (ISSPACE (str
[last
]))
744 /* Find next field separated by SEP and terminate it. Return a
745 pointer to the one after it. */
748 next_field (char *str
, char sep
, char **next
, char *last
)
752 p
= remove_leading_whitespaces (str
);
753 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
756 remove_trailing_whitespaces (p
);
766 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
769 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
,
770 int value
, unsigned int size
,
773 char *str
, *next
, *last
;
776 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
777 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
779 /* Turn on selective bits. */
780 char *init
= xstrdup (cpu_flag_init
[i
].init
);
781 last
= init
+ strlen (init
);
782 for (next
= init
; next
&& next
< last
; )
784 str
= next_field (next
, '|', &next
, last
);
786 set_bitfield (str
, array
, 1, size
, lineno
);
796 set_bitfield (char *f
, bitfield
*array
, int value
,
797 unsigned int size
, int lineno
)
801 if (strcmp (f
, "CpuFP") == 0)
803 set_bitfield("Cpu387", array
, value
, size
, lineno
);
804 set_bitfield("Cpu287", array
, value
, size
, lineno
);
807 else if (strcmp (f
, "Mmword") == 0)
809 else if (strcmp (f
, "Oword") == 0)
812 for (i
= 0; i
< size
; i
++)
813 if (strcasecmp (array
[i
].name
, f
) == 0)
815 array
[i
].value
= value
;
821 const char *v
= strchr (f
, '=');
828 for (i
= 0; i
< size
; i
++)
829 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
831 value
= strtol (v
+ 1, &end
, 0);
834 array
[i
].value
= value
;
842 /* Handle CPU_XXX_FLAGS. */
843 if (!set_bitfield_from_cpu_flag_init (f
, array
, value
, size
, lineno
))
847 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
849 fail (_("Unknown bitfield: %s\n"), f
);
853 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
854 int macro
, const char *comma
, const char *indent
)
858 fprintf (table
, "%s{ { ", indent
);
860 for (i
= 0; i
< size
- 1; i
++)
862 if (((i
+ 1) % 20) != 0)
863 fprintf (table
, "%d, ", flags
[i
].value
);
865 fprintf (table
, "%d,", flags
[i
].value
);
866 if (((i
+ 1) % 20) == 0)
868 /* We need \\ for macro. */
870 fprintf (table
, " \\\n %s", indent
);
872 fprintf (table
, "\n %s", indent
);
876 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
880 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
881 const char *comma
, const char *indent
,
884 char *str
, *next
, *last
;
886 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
888 /* Copy the default cpu flags. */
889 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
891 if (strcasecmp (flag
, "unknown") == 0)
893 /* We turn on everything except for cpu64 in case of
894 CPU_UNKNOWN_FLAGS. */
895 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
896 if (flags
[i
].position
!= Cpu64
)
899 else if (flag
[0] == '~')
901 last
= flag
+ strlen (flag
);
908 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
915 /* First we turn on everything except for cpu64. */
916 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
917 if (flags
[i
].position
!= Cpu64
)
920 /* Turn off selective bits. */
921 for (; next
&& next
< last
; )
923 str
= next_field (next
, '|', &next
, last
);
925 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
928 else if (strcmp (flag
, "0"))
930 /* Turn on selective bits. */
931 last
= flag
+ strlen (flag
);
932 for (next
= flag
; next
&& next
< last
; )
934 str
= next_field (next
, '|', &next
, last
);
936 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
940 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
945 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
949 fprintf (table
, " { ");
951 for (i
= 0; i
< size
- 1; i
++)
953 if (((i
+ 1) % 20) != 0)
954 fprintf (table
, "%d, ", modifier
[i
].value
);
956 fprintf (table
, "%d,", modifier
[i
].value
);
957 if (((i
+ 1) % 20) == 0)
958 fprintf (table
, "\n ");
961 fprintf (table
, "%d },\n", modifier
[i
].value
);
965 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
967 char *str
, *next
, *last
;
968 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
970 /* Copy the default opcode modifier. */
971 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
973 if (strcmp (mod
, "0"))
975 last
= mod
+ strlen (mod
);
976 for (next
= mod
; next
&& next
< last
; )
978 str
= next_field (next
, '|', &next
, last
);
980 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
984 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
988 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
989 int macro
, const char *indent
)
993 fprintf (table
, "{ { ");
995 for (i
= 0; i
< size
- 1; i
++)
997 if (((i
+ 1) % 20) != 0)
998 fprintf (table
, "%d, ", types
[i
].value
);
1000 fprintf (table
, "%d,", types
[i
].value
);
1001 if (((i
+ 1) % 20) == 0)
1003 /* We need \\ for macro. */
1005 fprintf (table
, " \\\n%s", indent
);
1007 fprintf (table
, "\n%s", indent
);
1011 fprintf (table
, "%d } }", types
[i
].value
);
1015 process_i386_operand_type (FILE *table
, char *op
, int macro
,
1016 const char *indent
, int lineno
)
1018 char *str
, *next
, *last
;
1019 bitfield types
[ARRAY_SIZE (operand_types
)];
1021 /* Copy the default operand type. */
1022 memcpy (types
, operand_types
, sizeof (types
));
1024 if (strcmp (op
, "0"))
1026 last
= op
+ strlen (op
);
1027 for (next
= op
; next
&& next
< last
; )
1029 str
= next_field (next
, '|', &next
, last
);
1031 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1034 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
1039 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1040 char *last
, int lineno
)
1043 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1044 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1046 /* Find number of operands. */
1047 operands
= next_field (str
, ',', &str
, last
);
1049 /* Find base_opcode. */
1050 base_opcode
= next_field (str
, ',', &str
, last
);
1052 /* Find extension_opcode. */
1053 extension_opcode
= next_field (str
, ',', &str
, last
);
1055 /* Find opcode_length. */
1056 opcode_length
= next_field (str
, ',', &str
, last
);
1058 /* Find cpu_flags. */
1059 cpu_flags
= next_field (str
, ',', &str
, last
);
1061 /* Find opcode_modifier. */
1062 opcode_modifier
= next_field (str
, ',', &str
, last
);
1064 /* Remove the first {. */
1065 str
= remove_leading_whitespaces (str
);
1068 str
= remove_leading_whitespaces (str
+ 1);
1072 /* There are at least "X}". */
1076 /* Remove trailing white spaces and }. */
1080 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1089 /* Find operand_types. */
1090 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1094 operand_types
[i
] = NULL
;
1098 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1099 if (*operand_types
[i
] == '0')
1102 operand_types
[i
] = NULL
;
1107 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1108 name
, operands
, base_opcode
, extension_opcode
,
1111 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1113 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
1115 fprintf (table
, " { ");
1117 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1119 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1122 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
1127 fprintf (table
, ",\n ");
1129 process_i386_operand_type (table
, operand_types
[i
], 0,
1132 fprintf (table
, " } },\n");
1135 struct opcode_hash_entry
1137 struct opcode_hash_entry
*next
;
1143 /* Calculate the hash value of an opcode hash entry P. */
1146 opcode_hash_hash (const void *p
)
1148 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1149 return htab_hash_string (entry
->name
);
1152 /* Compare a string Q against an opcode hash entry P. */
1155 opcode_hash_eq (const void *p
, const void *q
)
1157 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1158 const char *name
= (const char *) q
;
1159 return strcmp (name
, entry
->name
) == 0;
1163 process_i386_opcodes (FILE *table
)
1168 char *str
, *p
, *last
, *name
;
1169 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1170 htab_t opcode_hash_table
;
1171 struct opcode_hash_entry
**opcode_array
;
1172 unsigned int opcode_array_size
= 1024;
1175 filename
= "i386-opc.tbl";
1176 fp
= fopen (filename
, "r");
1179 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1183 opcode_array
= (struct opcode_hash_entry
**)
1184 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1186 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1187 opcode_hash_eq
, NULL
,
1190 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1191 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1193 /* Put everything on opcode array. */
1196 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1201 p
= remove_leading_whitespaces (buf
);
1203 /* Skip comments. */
1204 str
= strstr (p
, "//");
1208 /* Remove trailing white spaces. */
1209 remove_trailing_whitespaces (p
);
1214 /* Ignore comments. */
1222 last
= p
+ strlen (p
);
1225 name
= next_field (p
, ',', &str
, last
);
1227 /* Get the slot in hash table. */
1228 hash_slot
= (struct opcode_hash_entry
**)
1229 htab_find_slot_with_hash (opcode_hash_table
, name
,
1230 htab_hash_string (name
),
1233 if (*hash_slot
== NULL
)
1235 /* It is the new one. Put it on opcode array. */
1236 if (i
>= opcode_array_size
)
1238 /* Grow the opcode array when needed. */
1239 opcode_array_size
+= 1024;
1240 opcode_array
= (struct opcode_hash_entry
**)
1241 xrealloc (opcode_array
,
1242 sizeof (*opcode_array
) * opcode_array_size
);
1245 opcode_array
[i
] = (struct opcode_hash_entry
*)
1246 xmalloc (sizeof (struct opcode_hash_entry
));
1247 opcode_array
[i
]->next
= NULL
;
1248 opcode_array
[i
]->name
= xstrdup (name
);
1249 opcode_array
[i
]->opcode
= xstrdup (str
);
1250 opcode_array
[i
]->lineno
= lineno
;
1251 *hash_slot
= opcode_array
[i
];
1256 /* Append it to the existing one. */
1258 while ((*entry
) != NULL
)
1259 entry
= &(*entry
)->next
;
1260 *entry
= (struct opcode_hash_entry
*)
1261 xmalloc (sizeof (struct opcode_hash_entry
));
1262 (*entry
)->next
= NULL
;
1263 (*entry
)->name
= (*hash_slot
)->name
;
1264 (*entry
)->opcode
= xstrdup (str
);
1265 (*entry
)->lineno
= lineno
;
1269 /* Process opcode array. */
1270 for (j
= 0; j
< i
; j
++)
1272 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1276 lineno
= next
->lineno
;
1277 last
= str
+ strlen (str
);
1278 output_i386_opcode (table
, name
, str
, last
, lineno
);
1284 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1286 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1288 process_i386_opcode_modifier (table
, "0", -1);
1290 fprintf (table
, " { ");
1291 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1292 fprintf (table
, " } }\n");
1294 fprintf (table
, "};\n");
1298 process_i386_registers (FILE *table
)
1302 char *str
, *p
, *last
;
1303 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1304 char *dw2_32_num
, *dw2_64_num
;
1307 filename
= "i386-reg.tbl";
1308 fp
= fopen (filename
, "r");
1310 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1313 fprintf (table
, "\n/* i386 register table. */\n\n");
1314 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1318 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1323 p
= remove_leading_whitespaces (buf
);
1325 /* Skip comments. */
1326 str
= strstr (p
, "//");
1330 /* Remove trailing white spaces. */
1331 remove_trailing_whitespaces (p
);
1336 fprintf (table
, "%s\n", p
);
1344 last
= p
+ strlen (p
);
1346 /* Find reg_name. */
1347 reg_name
= next_field (p
, ',', &str
, last
);
1349 /* Find reg_type. */
1350 reg_type
= next_field (str
, ',', &str
, last
);
1352 /* Find reg_flags. */
1353 reg_flags
= next_field (str
, ',', &str
, last
);
1356 reg_num
= next_field (str
, ',', &str
, last
);
1358 fprintf (table
, " { \"%s\",\n ", reg_name
);
1360 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1362 /* Find 32-bit Dwarf2 register number. */
1363 dw2_32_num
= next_field (str
, ',', &str
, last
);
1365 /* Find 64-bit Dwarf2 register number. */
1366 dw2_64_num
= next_field (str
, ',', &str
, last
);
1368 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1369 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1374 fprintf (table
, "};\n");
1376 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1380 process_i386_initializers (void)
1383 FILE *fp
= fopen ("i386-init.h", "w");
1387 fail (_("can't create i386-init.h, errno = %s\n"),
1390 process_copyright (fp
);
1392 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1394 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1395 init
= xstrdup (cpu_flag_init
[i
].init
);
1396 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1400 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1402 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1403 init
= xstrdup (operand_type_init
[i
].init
);
1404 process_i386_operand_type (fp
, init
, 1, " ", -1);
1412 /* Program options. */
1413 #define OPTION_SRCDIR 200
1415 struct option long_options
[] =
1417 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1418 {"debug", no_argument
, NULL
, 'd'},
1419 {"version", no_argument
, NULL
, 'V'},
1420 {"help", no_argument
, NULL
, 'h'},
1421 {0, no_argument
, NULL
, 0}
1425 print_version (void)
1427 printf ("%s: version 1.0\n", program_name
);
1432 usage (FILE * stream
, int status
)
1434 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1440 main (int argc
, char **argv
)
1442 extern int chdir (char *);
1443 char *srcdir
= NULL
;
1445 unsigned int i
, cpumax
;
1448 program_name
= *argv
;
1449 xmalloc_set_program_name (program_name
);
1451 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1476 if (chdir (srcdir
) != 0)
1477 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1478 srcdir
, xstrerror (errno
));
1480 /* cpu_flags isn't sorted by position. */
1482 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1483 if (cpu_flags
[i
].position
> cpumax
)
1484 cpumax
= cpu_flags
[i
].position
;
1486 /* Check the unused bitfield in i386_cpu_flags. */
1488 if ((cpumax
- 1) != CpuMax
)
1489 fail (_("CpuMax != %d!\n"), cpumax
);
1491 if (cpumax
!= CpuMax
)
1492 fail (_("CpuMax != %d!\n"), cpumax
);
1494 c
= CpuNumOfBits
- CpuMax
- 1;
1496 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1499 /* Check the unused bitfield in i386_operand_type. */
1501 c
= OTNumOfBits
- OTMax
- 1;
1503 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1506 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1509 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1510 sizeof (opcode_modifiers
[0]), compare
);
1512 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1513 sizeof (operand_types
[0]), compare
);
1515 table
= fopen ("i386-tbl.h", "w");
1517 fail (_("can't create i386-tbl.h, errno = %s\n"),
1520 process_copyright (table
);
1522 process_i386_opcodes (table
);
1523 process_i386_registers (table
);
1524 process_i386_initializers ();