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" },
233 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
236 { "CPU_RDSEED_FLAGS",
238 { "CPU_PRFCHW_FLAGS",
245 "CPU_SSE2_FLAGS|CpuSHA" },
246 { "CPU_CLFLUSHOPT_FLAGS",
248 { "CPU_XSAVES_FLAGS",
249 "CPU_XSAVE_FLAGS|CpuXSAVES" },
250 { "CPU_XSAVEC_FLAGS",
251 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
252 { "CPU_PREFETCHWT1_FLAGS",
258 { "CPU_CLZERO_FLAGS",
260 { "CPU_MWAITX_FLAGS",
266 { "CPU_PTWRITE_FLAGS",
274 { "CPU_VPCLMULQDQ_FLAGS",
276 { "CPU_ANY_X87_FLAGS",
277 "CPU_ANY_287_FLAGS|Cpu8087" },
278 { "CPU_ANY_287_FLAGS",
279 "CPU_ANY_387_FLAGS|Cpu287" },
280 { "CPU_ANY_387_FLAGS",
281 "CPU_ANY_687_FLAGS|Cpu387" },
282 { "CPU_ANY_687_FLAGS",
283 "Cpu687|CpuFISTTP" },
284 { "CPU_ANY_MMX_FLAGS",
285 "CPU_3DNOWA_FLAGS" },
286 { "CPU_ANY_SSE_FLAGS",
287 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
288 { "CPU_ANY_SSE2_FLAGS",
289 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
290 { "CPU_ANY_SSE3_FLAGS",
291 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
292 { "CPU_ANY_SSSE3_FLAGS",
293 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
294 { "CPU_ANY_SSE4_1_FLAGS",
295 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
296 { "CPU_ANY_SSE4_2_FLAGS",
298 { "CPU_ANY_AVX_FLAGS",
299 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
300 { "CPU_ANY_AVX2_FLAGS",
302 { "CPU_ANY_AVX512F_FLAGS",
303 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512F" },
304 { "CPU_ANY_AVX512CD_FLAGS",
306 { "CPU_ANY_AVX512ER_FLAGS",
308 { "CPU_ANY_AVX512PF_FLAGS",
310 { "CPU_ANY_AVX512DQ_FLAGS",
312 { "CPU_ANY_AVX512BW_FLAGS",
314 { "CPU_ANY_AVX512VL_FLAGS",
316 { "CPU_ANY_AVX512IFMA_FLAGS",
318 { "CPU_ANY_AVX512VBMI_FLAGS",
320 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
321 "CpuAVX512_4FMAPS" },
322 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
323 "CpuAVX512_4VNNIW" },
324 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
325 "CpuAVX512_VPOPCNTDQ" },
326 { "CPU_ANY_AVX512_VBMI2_FLAGS",
330 static initializer operand_type_init
[] =
332 { "OPERAND_TYPE_NONE",
334 { "OPERAND_TYPE_REG8",
336 { "OPERAND_TYPE_REG16",
338 { "OPERAND_TYPE_REG32",
340 { "OPERAND_TYPE_REG64",
342 { "OPERAND_TYPE_IMM1",
344 { "OPERAND_TYPE_IMM8",
346 { "OPERAND_TYPE_IMM8S",
348 { "OPERAND_TYPE_IMM16",
350 { "OPERAND_TYPE_IMM32",
352 { "OPERAND_TYPE_IMM32S",
354 { "OPERAND_TYPE_IMM64",
356 { "OPERAND_TYPE_BASEINDEX",
358 { "OPERAND_TYPE_DISP8",
360 { "OPERAND_TYPE_DISP16",
362 { "OPERAND_TYPE_DISP32",
364 { "OPERAND_TYPE_DISP32S",
366 { "OPERAND_TYPE_DISP64",
368 { "OPERAND_TYPE_INOUTPORTREG",
370 { "OPERAND_TYPE_SHIFTCOUNT",
372 { "OPERAND_TYPE_CONTROL",
374 { "OPERAND_TYPE_TEST",
376 { "OPERAND_TYPE_DEBUG",
378 { "OPERAND_TYPE_FLOATREG",
380 { "OPERAND_TYPE_FLOATACC",
382 { "OPERAND_TYPE_SREG2",
384 { "OPERAND_TYPE_SREG3",
386 { "OPERAND_TYPE_ACC",
388 { "OPERAND_TYPE_JUMPABSOLUTE",
390 { "OPERAND_TYPE_REGMMX",
392 { "OPERAND_TYPE_REGXMM",
394 { "OPERAND_TYPE_REGYMM",
396 { "OPERAND_TYPE_REGZMM",
398 { "OPERAND_TYPE_REGMASK",
400 { "OPERAND_TYPE_ESSEG",
402 { "OPERAND_TYPE_ACC32",
404 { "OPERAND_TYPE_ACC64",
406 { "OPERAND_TYPE_INOUTPORTREG",
408 { "OPERAND_TYPE_REG16_INOUTPORTREG",
409 "Reg16|InOutPortReg" },
410 { "OPERAND_TYPE_DISP16_32",
412 { "OPERAND_TYPE_ANYDISP",
413 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
414 { "OPERAND_TYPE_IMM16_32",
416 { "OPERAND_TYPE_IMM16_32S",
418 { "OPERAND_TYPE_IMM16_32_32S",
419 "Imm16|Imm32|Imm32S" },
420 { "OPERAND_TYPE_IMM32_64",
422 { "OPERAND_TYPE_IMM32_32S_DISP32",
423 "Imm32|Imm32S|Disp32" },
424 { "OPERAND_TYPE_IMM64_DISP64",
426 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
427 "Imm32|Imm32S|Imm64|Disp32" },
428 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
429 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
430 { "OPERAND_TYPE_VEC_IMM4",
432 { "OPERAND_TYPE_REGBND",
434 { "OPERAND_TYPE_VEC_DISP8",
438 typedef struct bitfield
445 #define BITFIELD(n) { n, 0, #n }
447 static bitfield cpu_flags
[] =
455 BITFIELD (CpuClflush
),
457 BITFIELD (CpuSYSCALL
),
462 BITFIELD (CpuFISTTP
),
468 BITFIELD (CpuSSE4_1
),
469 BITFIELD (CpuSSE4_2
),
472 BITFIELD (CpuAVX512F
),
473 BITFIELD (CpuAVX512CD
),
474 BITFIELD (CpuAVX512ER
),
475 BITFIELD (CpuAVX512PF
),
476 BITFIELD (CpuAVX512VL
),
477 BITFIELD (CpuAVX512DQ
),
478 BITFIELD (CpuAVX512BW
),
484 BITFIELD (Cpu3dnowA
),
485 BITFIELD (CpuPadLock
),
491 BITFIELD (CpuXsaveopt
),
493 BITFIELD (CpuPCLMUL
),
504 BITFIELD (CpuRdtscp
),
505 BITFIELD (CpuFSGSBase
),
512 BITFIELD (CpuINVPCID
),
513 BITFIELD (CpuVMFUNC
),
514 BITFIELD (CpuRDSEED
),
516 BITFIELD (CpuPRFCHW
),
520 BITFIELD (CpuClflushOpt
),
521 BITFIELD (CpuXSAVES
),
522 BITFIELD (CpuXSAVEC
),
523 BITFIELD (CpuPREFETCHWT1
),
529 BITFIELD (CpuAVX512IFMA
),
530 BITFIELD (CpuAVX512VBMI
),
531 BITFIELD (CpuAVX512_4FMAPS
),
532 BITFIELD (CpuAVX512_4VNNIW
),
533 BITFIELD (CpuAVX512_VPOPCNTDQ
),
534 BITFIELD (CpuAVX512_VBMI2
),
535 BITFIELD (CpuMWAITX
),
536 BITFIELD (CpuCLZERO
),
539 BITFIELD (CpuPTWRITE
),
543 BITFIELD (CpuVPCLMULQDQ
),
544 BITFIELD (CpuRegMMX
),
545 BITFIELD (CpuRegXMM
),
546 BITFIELD (CpuRegYMM
),
547 BITFIELD (CpuRegZMM
),
548 BITFIELD (CpuRegMask
),
550 BITFIELD (CpuUnused
),
554 static bitfield opcode_modifiers
[] =
560 BITFIELD (ShortForm
),
562 BITFIELD (JumpDword
),
564 BITFIELD (JumpInterSegment
),
571 BITFIELD (CheckRegSize
),
572 BITFIELD (IgnoreSize
),
573 BITFIELD (DefaultSize
),
582 BITFIELD (BNDPrefixOk
),
583 BITFIELD (NoTrackPrefixOk
),
584 BITFIELD (IsLockable
),
585 BITFIELD (RegKludge
),
586 BITFIELD (FirstXmm0
),
587 BITFIELD (Implicit1stXmm0
),
588 BITFIELD (RepPrefixOk
),
589 BITFIELD (HLEPrefixOk
),
592 BITFIELD (AddrPrefixOp0
),
601 BITFIELD (VexOpcode
),
602 BITFIELD (VexSources
),
603 BITFIELD (VexImmExt
),
610 BITFIELD (Broadcast
),
611 BITFIELD (StaticRounding
),
613 BITFIELD (Disp8MemShift
),
614 BITFIELD (NoDefMask
),
615 BITFIELD (ImplicitQuadGroup
),
617 BITFIELD (ATTMnemonic
),
618 BITFIELD (ATTSyntax
),
619 BITFIELD (IntelSyntax
),
624 static bitfield operand_types
[] =
643 BITFIELD (BaseIndex
),
649 BITFIELD (InOutPortReg
),
650 BITFIELD (ShiftCount
),
658 BITFIELD (JumpAbsolute
),
671 BITFIELD (Unspecified
),
675 BITFIELD (Vec_Disp8
),
681 static const char *filename
;
684 compare (const void *x
, const void *y
)
686 const bitfield
*xp
= (const bitfield
*) x
;
687 const bitfield
*yp
= (const bitfield
*) y
;
688 return xp
->position
- yp
->position
;
692 fail (const char *message
, ...)
696 va_start (args
, message
);
697 fprintf (stderr
, _("%s: Error: "), program_name
);
698 vfprintf (stderr
, message
, args
);
704 process_copyright (FILE *fp
)
706 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
707 /* Copyright (C) 2007-2017 Free Software Foundation, Inc.\n\
709 This file is part of the GNU opcodes library.\n\
711 This library is free software; you can redistribute it and/or modify\n\
712 it under the terms of the GNU General Public License as published by\n\
713 the Free Software Foundation; either version 3, or (at your option)\n\
714 any later version.\n\
716 It is distributed in the hope that it will be useful, but WITHOUT\n\
717 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
718 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
719 License for more details.\n\
721 You should have received a copy of the GNU General Public License\n\
722 along with this program; if not, write to the Free Software\n\
723 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
724 MA 02110-1301, USA. */\n");
727 /* Remove leading white spaces. */
730 remove_leading_whitespaces (char *str
)
732 while (ISSPACE (*str
))
737 /* Remove trailing white spaces. */
740 remove_trailing_whitespaces (char *str
)
742 size_t last
= strlen (str
);
750 if (ISSPACE (str
[last
]))
758 /* Find next field separated by SEP and terminate it. Return a
759 pointer to the one after it. */
762 next_field (char *str
, char sep
, char **next
, char *last
)
766 p
= remove_leading_whitespaces (str
);
767 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
770 remove_trailing_whitespaces (p
);
780 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
783 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
,
784 int value
, unsigned int size
,
787 char *str
, *next
, *last
;
790 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
791 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
793 /* Turn on selective bits. */
794 char *init
= xstrdup (cpu_flag_init
[i
].init
);
795 last
= init
+ strlen (init
);
796 for (next
= init
; next
&& next
< last
; )
798 str
= next_field (next
, '|', &next
, last
);
800 set_bitfield (str
, array
, 1, size
, lineno
);
810 set_bitfield (char *f
, bitfield
*array
, int value
,
811 unsigned int size
, int lineno
)
815 if (strcmp (f
, "CpuFP") == 0)
817 set_bitfield("Cpu387", array
, value
, size
, lineno
);
818 set_bitfield("Cpu287", array
, value
, size
, lineno
);
821 else if (strcmp (f
, "Mmword") == 0)
823 else if (strcmp (f
, "Oword") == 0)
826 for (i
= 0; i
< size
; i
++)
827 if (strcasecmp (array
[i
].name
, f
) == 0)
829 array
[i
].value
= value
;
835 const char *v
= strchr (f
, '=');
842 for (i
= 0; i
< size
; i
++)
843 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
845 value
= strtol (v
+ 1, &end
, 0);
848 array
[i
].value
= value
;
856 /* Handle CPU_XXX_FLAGS. */
857 if (!set_bitfield_from_cpu_flag_init (f
, array
, value
, size
, lineno
))
861 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
863 fail (_("Unknown bitfield: %s\n"), f
);
867 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
868 int macro
, const char *comma
, const char *indent
)
872 fprintf (table
, "%s{ { ", indent
);
874 for (i
= 0; i
< size
- 1; i
++)
876 if (((i
+ 1) % 20) != 0)
877 fprintf (table
, "%d, ", flags
[i
].value
);
879 fprintf (table
, "%d,", flags
[i
].value
);
880 if (((i
+ 1) % 20) == 0)
882 /* We need \\ for macro. */
884 fprintf (table
, " \\\n %s", indent
);
886 fprintf (table
, "\n %s", indent
);
890 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
894 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
895 const char *comma
, const char *indent
,
898 char *str
, *next
, *last
;
900 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
902 /* Copy the default cpu flags. */
903 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
905 if (strcasecmp (flag
, "unknown") == 0)
907 /* We turn on everything except for cpu64 in case of
908 CPU_UNKNOWN_FLAGS. */
909 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
910 if (flags
[i
].position
!= Cpu64
)
913 else if (flag
[0] == '~')
915 last
= flag
+ strlen (flag
);
922 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
929 /* First we turn on everything except for cpu64. */
930 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
931 if (flags
[i
].position
!= Cpu64
)
934 /* Turn off selective bits. */
935 for (; next
&& next
< last
; )
937 str
= next_field (next
, '|', &next
, last
);
939 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
942 else if (strcmp (flag
, "0"))
944 /* Turn on selective bits. */
945 last
= flag
+ strlen (flag
);
946 for (next
= flag
; next
&& next
< last
; )
948 str
= next_field (next
, '|', &next
, last
);
950 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
954 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
959 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
963 fprintf (table
, " { ");
965 for (i
= 0; i
< size
- 1; i
++)
967 if (((i
+ 1) % 20) != 0)
968 fprintf (table
, "%d, ", modifier
[i
].value
);
970 fprintf (table
, "%d,", modifier
[i
].value
);
971 if (((i
+ 1) % 20) == 0)
972 fprintf (table
, "\n ");
975 fprintf (table
, "%d },\n", modifier
[i
].value
);
979 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
981 char *str
, *next
, *last
;
982 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
984 /* Copy the default opcode modifier. */
985 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
987 if (strcmp (mod
, "0"))
989 last
= mod
+ strlen (mod
);
990 for (next
= mod
; next
&& next
< last
; )
992 str
= next_field (next
, '|', &next
, last
);
994 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
998 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1002 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
1003 int macro
, const char *indent
)
1007 fprintf (table
, "{ { ");
1009 for (i
= 0; i
< size
- 1; i
++)
1011 if (((i
+ 1) % 20) != 0)
1012 fprintf (table
, "%d, ", types
[i
].value
);
1014 fprintf (table
, "%d,", types
[i
].value
);
1015 if (((i
+ 1) % 20) == 0)
1017 /* We need \\ for macro. */
1019 fprintf (table
, " \\\n%s", indent
);
1021 fprintf (table
, "\n%s", indent
);
1025 fprintf (table
, "%d } }", types
[i
].value
);
1029 process_i386_operand_type (FILE *table
, char *op
, int macro
,
1030 const char *indent
, int lineno
)
1032 char *str
, *next
, *last
;
1033 bitfield types
[ARRAY_SIZE (operand_types
)];
1035 /* Copy the default operand type. */
1036 memcpy (types
, operand_types
, sizeof (types
));
1038 if (strcmp (op
, "0"))
1040 last
= op
+ strlen (op
);
1041 for (next
= op
; next
&& next
< last
; )
1043 str
= next_field (next
, '|', &next
, last
);
1045 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1048 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
1053 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1054 char *last
, int lineno
)
1057 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1058 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1060 /* Find number of operands. */
1061 operands
= next_field (str
, ',', &str
, last
);
1063 /* Find base_opcode. */
1064 base_opcode
= next_field (str
, ',', &str
, last
);
1066 /* Find extension_opcode. */
1067 extension_opcode
= next_field (str
, ',', &str
, last
);
1069 /* Find opcode_length. */
1070 opcode_length
= next_field (str
, ',', &str
, last
);
1072 /* Find cpu_flags. */
1073 cpu_flags
= next_field (str
, ',', &str
, last
);
1075 /* Find opcode_modifier. */
1076 opcode_modifier
= next_field (str
, ',', &str
, last
);
1078 /* Remove the first {. */
1079 str
= remove_leading_whitespaces (str
);
1082 str
= remove_leading_whitespaces (str
+ 1);
1086 /* There are at least "X}". */
1090 /* Remove trailing white spaces and }. */
1094 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1103 /* Find operand_types. */
1104 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1108 operand_types
[i
] = NULL
;
1112 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1113 if (*operand_types
[i
] == '0')
1116 operand_types
[i
] = NULL
;
1121 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1122 name
, operands
, base_opcode
, extension_opcode
,
1125 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1127 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
1129 fprintf (table
, " { ");
1131 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1133 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1136 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
1141 fprintf (table
, ",\n ");
1143 process_i386_operand_type (table
, operand_types
[i
], 0,
1146 fprintf (table
, " } },\n");
1149 struct opcode_hash_entry
1151 struct opcode_hash_entry
*next
;
1157 /* Calculate the hash value of an opcode hash entry P. */
1160 opcode_hash_hash (const void *p
)
1162 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1163 return htab_hash_string (entry
->name
);
1166 /* Compare a string Q against an opcode hash entry P. */
1169 opcode_hash_eq (const void *p
, const void *q
)
1171 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1172 const char *name
= (const char *) q
;
1173 return strcmp (name
, entry
->name
) == 0;
1177 process_i386_opcodes (FILE *table
)
1182 char *str
, *p
, *last
, *name
;
1183 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1184 htab_t opcode_hash_table
;
1185 struct opcode_hash_entry
**opcode_array
;
1186 unsigned int opcode_array_size
= 1024;
1189 filename
= "i386-opc.tbl";
1190 fp
= fopen (filename
, "r");
1193 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1197 opcode_array
= (struct opcode_hash_entry
**)
1198 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1200 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1201 opcode_hash_eq
, NULL
,
1204 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1205 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1207 /* Put everything on opcode array. */
1210 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1215 p
= remove_leading_whitespaces (buf
);
1217 /* Skip comments. */
1218 str
= strstr (p
, "//");
1222 /* Remove trailing white spaces. */
1223 remove_trailing_whitespaces (p
);
1228 /* Ignore comments. */
1236 last
= p
+ strlen (p
);
1239 name
= next_field (p
, ',', &str
, last
);
1241 /* Get the slot in hash table. */
1242 hash_slot
= (struct opcode_hash_entry
**)
1243 htab_find_slot_with_hash (opcode_hash_table
, name
,
1244 htab_hash_string (name
),
1247 if (*hash_slot
== NULL
)
1249 /* It is the new one. Put it on opcode array. */
1250 if (i
>= opcode_array_size
)
1252 /* Grow the opcode array when needed. */
1253 opcode_array_size
+= 1024;
1254 opcode_array
= (struct opcode_hash_entry
**)
1255 xrealloc (opcode_array
,
1256 sizeof (*opcode_array
) * opcode_array_size
);
1259 opcode_array
[i
] = (struct opcode_hash_entry
*)
1260 xmalloc (sizeof (struct opcode_hash_entry
));
1261 opcode_array
[i
]->next
= NULL
;
1262 opcode_array
[i
]->name
= xstrdup (name
);
1263 opcode_array
[i
]->opcode
= xstrdup (str
);
1264 opcode_array
[i
]->lineno
= lineno
;
1265 *hash_slot
= opcode_array
[i
];
1270 /* Append it to the existing one. */
1272 while ((*entry
) != NULL
)
1273 entry
= &(*entry
)->next
;
1274 *entry
= (struct opcode_hash_entry
*)
1275 xmalloc (sizeof (struct opcode_hash_entry
));
1276 (*entry
)->next
= NULL
;
1277 (*entry
)->name
= (*hash_slot
)->name
;
1278 (*entry
)->opcode
= xstrdup (str
);
1279 (*entry
)->lineno
= lineno
;
1283 /* Process opcode array. */
1284 for (j
= 0; j
< i
; j
++)
1286 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1290 lineno
= next
->lineno
;
1291 last
= str
+ strlen (str
);
1292 output_i386_opcode (table
, name
, str
, last
, lineno
);
1298 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1300 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1302 process_i386_opcode_modifier (table
, "0", -1);
1304 fprintf (table
, " { ");
1305 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1306 fprintf (table
, " } }\n");
1308 fprintf (table
, "};\n");
1312 process_i386_registers (FILE *table
)
1316 char *str
, *p
, *last
;
1317 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1318 char *dw2_32_num
, *dw2_64_num
;
1321 filename
= "i386-reg.tbl";
1322 fp
= fopen (filename
, "r");
1324 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1327 fprintf (table
, "\n/* i386 register table. */\n\n");
1328 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1332 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1337 p
= remove_leading_whitespaces (buf
);
1339 /* Skip comments. */
1340 str
= strstr (p
, "//");
1344 /* Remove trailing white spaces. */
1345 remove_trailing_whitespaces (p
);
1350 fprintf (table
, "%s\n", p
);
1358 last
= p
+ strlen (p
);
1360 /* Find reg_name. */
1361 reg_name
= next_field (p
, ',', &str
, last
);
1363 /* Find reg_type. */
1364 reg_type
= next_field (str
, ',', &str
, last
);
1366 /* Find reg_flags. */
1367 reg_flags
= next_field (str
, ',', &str
, last
);
1370 reg_num
= next_field (str
, ',', &str
, last
);
1372 fprintf (table
, " { \"%s\",\n ", reg_name
);
1374 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1376 /* Find 32-bit Dwarf2 register number. */
1377 dw2_32_num
= next_field (str
, ',', &str
, last
);
1379 /* Find 64-bit Dwarf2 register number. */
1380 dw2_64_num
= next_field (str
, ',', &str
, last
);
1382 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1383 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1388 fprintf (table
, "};\n");
1390 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1394 process_i386_initializers (void)
1397 FILE *fp
= fopen ("i386-init.h", "w");
1401 fail (_("can't create i386-init.h, errno = %s\n"),
1404 process_copyright (fp
);
1406 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1408 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1409 init
= xstrdup (cpu_flag_init
[i
].init
);
1410 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1414 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1416 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1417 init
= xstrdup (operand_type_init
[i
].init
);
1418 process_i386_operand_type (fp
, init
, 1, " ", -1);
1426 /* Program options. */
1427 #define OPTION_SRCDIR 200
1429 struct option long_options
[] =
1431 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1432 {"debug", no_argument
, NULL
, 'd'},
1433 {"version", no_argument
, NULL
, 'V'},
1434 {"help", no_argument
, NULL
, 'h'},
1435 {0, no_argument
, NULL
, 0}
1439 print_version (void)
1441 printf ("%s: version 1.0\n", program_name
);
1446 usage (FILE * stream
, int status
)
1448 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1454 main (int argc
, char **argv
)
1456 extern int chdir (char *);
1457 char *srcdir
= NULL
;
1459 unsigned int i
, cpumax
;
1462 program_name
= *argv
;
1463 xmalloc_set_program_name (program_name
);
1465 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1490 if (chdir (srcdir
) != 0)
1491 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1492 srcdir
, xstrerror (errno
));
1494 /* cpu_flags isn't sorted by position. */
1496 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1497 if (cpu_flags
[i
].position
> cpumax
)
1498 cpumax
= cpu_flags
[i
].position
;
1500 /* Check the unused bitfield in i386_cpu_flags. */
1502 if ((cpumax
- 1) != CpuMax
)
1503 fail (_("CpuMax != %d!\n"), cpumax
);
1505 if (cpumax
!= CpuMax
)
1506 fail (_("CpuMax != %d!\n"), cpumax
);
1508 c
= CpuNumOfBits
- CpuMax
- 1;
1510 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1513 /* Check the unused bitfield in i386_operand_type. */
1515 c
= OTNumOfBits
- OTMax
- 1;
1517 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1520 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1523 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1524 sizeof (opcode_modifiers
[0]), compare
);
1526 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1527 sizeof (operand_types
[0]), compare
);
1529 table
= fopen ("i386-tbl.h", "w");
1531 fail (_("can't create i386-tbl.h, errno = %s\n"),
1534 process_copyright (table
);
1536 process_i386_opcodes (table
);
1537 process_i386_registers (table
);
1538 process_i386_initializers ();