1 /* Copyright (C) 2007-2016 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" },
225 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
228 { "CPU_RDSEED_FLAGS",
230 { "CPU_PRFCHW_FLAGS",
237 "CPU_SSE2_FLAGS|CpuSHA" },
238 { "CPU_CLFLUSHOPT_FLAGS",
240 { "CPU_XSAVES_FLAGS",
241 "CPU_XSAVE_FLAGS|CpuXSAVES" },
242 { "CPU_XSAVEC_FLAGS",
243 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
244 { "CPU_PREFETCHWT1_FLAGS",
250 { "CPU_CLZERO_FLAGS",
252 { "CPU_MWAITX_FLAGS",
258 { "CPU_PTWRITE_FLAGS",
260 { "CPU_ANY_X87_FLAGS",
261 "CPU_ANY_287_FLAGS|Cpu8087" },
262 { "CPU_ANY_287_FLAGS",
263 "CPU_ANY_387_FLAGS|Cpu287" },
264 { "CPU_ANY_387_FLAGS",
265 "CPU_ANY_687_FLAGS|Cpu387" },
266 { "CPU_ANY_687_FLAGS",
267 "Cpu687|CpuFISTTP" },
268 { "CPU_ANY_MMX_FLAGS",
269 "CPU_3DNOWA_FLAGS" },
270 { "CPU_ANY_SSE_FLAGS",
271 "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
272 { "CPU_ANY_SSE2_FLAGS",
273 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
274 { "CPU_ANY_SSE3_FLAGS",
275 "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
276 { "CPU_ANY_SSSE3_FLAGS",
277 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
278 { "CPU_ANY_SSE4_1_FLAGS",
279 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
280 { "CPU_ANY_SSE4_2_FLAGS",
282 { "CPU_ANY_AVX_FLAGS",
283 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
284 { "CPU_ANY_AVX2_FLAGS",
286 { "CPU_ANY_AVX512F_FLAGS",
287 "CpuVREX|CpuRegZMM|CpuRegMask|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512F" },
288 { "CPU_ANY_AVX512CD_FLAGS",
290 { "CPU_ANY_AVX512ER_FLAGS",
292 { "CPU_ANY_AVX512PF_FLAGS",
294 { "CPU_ANY_AVX512DQ_FLAGS",
296 { "CPU_ANY_AVX512BW_FLAGS",
298 { "CPU_ANY_AVX512VL_FLAGS",
300 { "CPU_ANY_AVX512IFMA_FLAGS",
302 { "CPU_ANY_AVX512VBMI_FLAGS",
306 static initializer operand_type_init
[] =
308 { "OPERAND_TYPE_NONE",
310 { "OPERAND_TYPE_REG8",
312 { "OPERAND_TYPE_REG16",
314 { "OPERAND_TYPE_REG32",
316 { "OPERAND_TYPE_REG64",
318 { "OPERAND_TYPE_IMM1",
320 { "OPERAND_TYPE_IMM8",
322 { "OPERAND_TYPE_IMM8S",
324 { "OPERAND_TYPE_IMM16",
326 { "OPERAND_TYPE_IMM32",
328 { "OPERAND_TYPE_IMM32S",
330 { "OPERAND_TYPE_IMM64",
332 { "OPERAND_TYPE_BASEINDEX",
334 { "OPERAND_TYPE_DISP8",
336 { "OPERAND_TYPE_DISP16",
338 { "OPERAND_TYPE_DISP32",
340 { "OPERAND_TYPE_DISP32S",
342 { "OPERAND_TYPE_DISP64",
344 { "OPERAND_TYPE_INOUTPORTREG",
346 { "OPERAND_TYPE_SHIFTCOUNT",
348 { "OPERAND_TYPE_CONTROL",
350 { "OPERAND_TYPE_TEST",
352 { "OPERAND_TYPE_DEBUG",
354 { "OPERAND_TYPE_FLOATREG",
356 { "OPERAND_TYPE_FLOATACC",
358 { "OPERAND_TYPE_SREG2",
360 { "OPERAND_TYPE_SREG3",
362 { "OPERAND_TYPE_ACC",
364 { "OPERAND_TYPE_JUMPABSOLUTE",
366 { "OPERAND_TYPE_REGMMX",
368 { "OPERAND_TYPE_REGXMM",
370 { "OPERAND_TYPE_REGYMM",
372 { "OPERAND_TYPE_REGZMM",
374 { "OPERAND_TYPE_REGMASK",
376 { "OPERAND_TYPE_ESSEG",
378 { "OPERAND_TYPE_ACC32",
380 { "OPERAND_TYPE_ACC64",
382 { "OPERAND_TYPE_INOUTPORTREG",
384 { "OPERAND_TYPE_REG16_INOUTPORTREG",
385 "Reg16|InOutPortReg" },
386 { "OPERAND_TYPE_DISP16_32",
388 { "OPERAND_TYPE_ANYDISP",
389 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
390 { "OPERAND_TYPE_IMM16_32",
392 { "OPERAND_TYPE_IMM16_32S",
394 { "OPERAND_TYPE_IMM16_32_32S",
395 "Imm16|Imm32|Imm32S" },
396 { "OPERAND_TYPE_IMM32_64",
398 { "OPERAND_TYPE_IMM32_32S_DISP32",
399 "Imm32|Imm32S|Disp32" },
400 { "OPERAND_TYPE_IMM64_DISP64",
402 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
403 "Imm32|Imm32S|Imm64|Disp32" },
404 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
405 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
406 { "OPERAND_TYPE_VEC_IMM4",
408 { "OPERAND_TYPE_REGBND",
410 { "OPERAND_TYPE_VEC_DISP8",
414 typedef struct bitfield
421 #define BITFIELD(n) { n, 0, #n }
423 static bitfield cpu_flags
[] =
431 BITFIELD (CpuClflush
),
433 BITFIELD (CpuSYSCALL
),
438 BITFIELD (CpuFISTTP
),
444 BITFIELD (CpuSSE4_1
),
445 BITFIELD (CpuSSE4_2
),
448 BITFIELD (CpuAVX512F
),
449 BITFIELD (CpuAVX512CD
),
450 BITFIELD (CpuAVX512ER
),
451 BITFIELD (CpuAVX512PF
),
452 BITFIELD (CpuAVX512VL
),
453 BITFIELD (CpuAVX512DQ
),
454 BITFIELD (CpuAVX512BW
),
460 BITFIELD (Cpu3dnowA
),
461 BITFIELD (CpuPadLock
),
467 BITFIELD (CpuXsaveopt
),
469 BITFIELD (CpuPCLMUL
),
480 BITFIELD (CpuRdtscp
),
481 BITFIELD (CpuFSGSBase
),
488 BITFIELD (CpuINVPCID
),
489 BITFIELD (CpuVMFUNC
),
490 BITFIELD (CpuRDSEED
),
492 BITFIELD (CpuPRFCHW
),
496 BITFIELD (CpuClflushOpt
),
497 BITFIELD (CpuXSAVES
),
498 BITFIELD (CpuXSAVEC
),
499 BITFIELD (CpuPREFETCHWT1
),
505 BITFIELD (CpuAVX512IFMA
),
506 BITFIELD (CpuAVX512VBMI
),
507 BITFIELD (CpuMWAITX
),
508 BITFIELD (CpuCLZERO
),
511 BITFIELD (CpuPTWRITE
),
512 BITFIELD (CpuRegMMX
),
513 BITFIELD (CpuRegXMM
),
514 BITFIELD (CpuRegYMM
),
515 BITFIELD (CpuRegZMM
),
516 BITFIELD (CpuRegMask
),
518 BITFIELD (CpuUnused
),
522 static bitfield opcode_modifiers
[] =
528 BITFIELD (ShortForm
),
530 BITFIELD (JumpDword
),
532 BITFIELD (JumpInterSegment
),
539 BITFIELD (CheckRegSize
),
540 BITFIELD (IgnoreSize
),
541 BITFIELD (DefaultSize
),
550 BITFIELD (BNDPrefixOk
),
551 BITFIELD (IsLockable
),
552 BITFIELD (RegKludge
),
553 BITFIELD (FirstXmm0
),
554 BITFIELD (Implicit1stXmm0
),
555 BITFIELD (RepPrefixOk
),
556 BITFIELD (HLEPrefixOk
),
559 BITFIELD (AddrPrefixOp0
),
568 BITFIELD (VexOpcode
),
569 BITFIELD (VexSources
),
570 BITFIELD (VexImmExt
),
577 BITFIELD (Broadcast
),
578 BITFIELD (StaticRounding
),
580 BITFIELD (Disp8MemShift
),
581 BITFIELD (NoDefMask
),
583 BITFIELD (ATTMnemonic
),
584 BITFIELD (ATTSyntax
),
585 BITFIELD (IntelSyntax
),
590 static bitfield operand_types
[] =
609 BITFIELD (BaseIndex
),
615 BITFIELD (InOutPortReg
),
616 BITFIELD (ShiftCount
),
624 BITFIELD (JumpAbsolute
),
637 BITFIELD (Unspecified
),
641 BITFIELD (Vec_Disp8
),
647 static const char *filename
;
650 compare (const void *x
, const void *y
)
652 const bitfield
*xp
= (const bitfield
*) x
;
653 const bitfield
*yp
= (const bitfield
*) y
;
654 return xp
->position
- yp
->position
;
658 fail (const char *message
, ...)
662 va_start (args
, message
);
663 fprintf (stderr
, _("%s: Error: "), program_name
);
664 vfprintf (stderr
, message
, args
);
670 process_copyright (FILE *fp
)
672 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
673 /* Copyright (C) 2007-2016 Free Software Foundation, Inc.\n\
675 This file is part of the GNU opcodes library.\n\
677 This library is free software; you can redistribute it and/or modify\n\
678 it under the terms of the GNU General Public License as published by\n\
679 the Free Software Foundation; either version 3, or (at your option)\n\
680 any later version.\n\
682 It is distributed in the hope that it will be useful, but WITHOUT\n\
683 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
684 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
685 License for more details.\n\
687 You should have received a copy of the GNU General Public License\n\
688 along with this program; if not, write to the Free Software\n\
689 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
690 MA 02110-1301, USA. */\n");
693 /* Remove leading white spaces. */
696 remove_leading_whitespaces (char *str
)
698 while (ISSPACE (*str
))
703 /* Remove trailing white spaces. */
706 remove_trailing_whitespaces (char *str
)
708 size_t last
= strlen (str
);
716 if (ISSPACE (str
[last
]))
724 /* Find next field separated by SEP and terminate it. Return a
725 pointer to the one after it. */
728 next_field (char *str
, char sep
, char **next
, char *last
)
732 p
= remove_leading_whitespaces (str
);
733 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
736 remove_trailing_whitespaces (p
);
746 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
749 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
,
750 int value
, unsigned int size
,
753 char *str
, *next
, *last
;
756 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
757 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
759 /* Turn on selective bits. */
760 char *init
= xstrdup (cpu_flag_init
[i
].init
);
761 last
= init
+ strlen (init
);
762 for (next
= init
; next
&& next
< last
; )
764 str
= next_field (next
, '|', &next
, last
);
766 set_bitfield (str
, array
, 1, size
, lineno
);
776 set_bitfield (char *f
, bitfield
*array
, int value
,
777 unsigned int size
, int lineno
)
781 if (strcmp (f
, "CpuFP") == 0)
783 set_bitfield("Cpu387", array
, value
, size
, lineno
);
784 set_bitfield("Cpu287", array
, value
, size
, lineno
);
787 else if (strcmp (f
, "Mmword") == 0)
789 else if (strcmp (f
, "Oword") == 0)
792 for (i
= 0; i
< size
; i
++)
793 if (strcasecmp (array
[i
].name
, f
) == 0)
795 array
[i
].value
= value
;
801 const char *v
= strchr (f
, '=');
808 for (i
= 0; i
< size
; i
++)
809 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
811 value
= strtol (v
+ 1, &end
, 0);
814 array
[i
].value
= value
;
822 /* Handle CPU_XXX_FLAGS. */
823 if (!set_bitfield_from_cpu_flag_init (f
, array
, value
, size
, lineno
))
827 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
829 fail (_("Unknown bitfield: %s\n"), f
);
833 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
834 int macro
, const char *comma
, const char *indent
)
838 fprintf (table
, "%s{ { ", indent
);
840 for (i
= 0; i
< size
- 1; i
++)
842 if (((i
+ 1) % 20) != 0)
843 fprintf (table
, "%d, ", flags
[i
].value
);
845 fprintf (table
, "%d,", flags
[i
].value
);
846 if (((i
+ 1) % 20) == 0)
848 /* We need \\ for macro. */
850 fprintf (table
, " \\\n %s", indent
);
852 fprintf (table
, "\n %s", indent
);
856 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
860 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
861 const char *comma
, const char *indent
,
864 char *str
, *next
, *last
;
866 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
868 /* Copy the default cpu flags. */
869 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
871 if (strcasecmp (flag
, "unknown") == 0)
873 /* We turn on everything except for cpu64 in case of
874 CPU_UNKNOWN_FLAGS. */
875 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
876 if (flags
[i
].position
!= Cpu64
)
879 else if (flag
[0] == '~')
881 last
= flag
+ strlen (flag
);
888 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
895 /* First we turn on everything except for cpu64. */
896 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
897 if (flags
[i
].position
!= Cpu64
)
900 /* Turn off selective bits. */
901 for (; next
&& next
< last
; )
903 str
= next_field (next
, '|', &next
, last
);
905 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
908 else if (strcmp (flag
, "0"))
910 /* Turn on selective bits. */
911 last
= flag
+ strlen (flag
);
912 for (next
= flag
; next
&& next
< last
; )
914 str
= next_field (next
, '|', &next
, last
);
916 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
920 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
925 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
929 fprintf (table
, " { ");
931 for (i
= 0; i
< size
- 1; i
++)
933 if (((i
+ 1) % 20) != 0)
934 fprintf (table
, "%d, ", modifier
[i
].value
);
936 fprintf (table
, "%d,", modifier
[i
].value
);
937 if (((i
+ 1) % 20) == 0)
938 fprintf (table
, "\n ");
941 fprintf (table
, "%d },\n", modifier
[i
].value
);
945 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
947 char *str
, *next
, *last
;
948 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
950 /* Copy the default opcode modifier. */
951 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
953 if (strcmp (mod
, "0"))
955 last
= mod
+ strlen (mod
);
956 for (next
= mod
; next
&& next
< last
; )
958 str
= next_field (next
, '|', &next
, last
);
960 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
964 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
968 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
969 int macro
, const char *indent
)
973 fprintf (table
, "{ { ");
975 for (i
= 0; i
< size
- 1; i
++)
977 if (((i
+ 1) % 20) != 0)
978 fprintf (table
, "%d, ", types
[i
].value
);
980 fprintf (table
, "%d,", types
[i
].value
);
981 if (((i
+ 1) % 20) == 0)
983 /* We need \\ for macro. */
985 fprintf (table
, " \\\n%s", indent
);
987 fprintf (table
, "\n%s", indent
);
991 fprintf (table
, "%d } }", types
[i
].value
);
995 process_i386_operand_type (FILE *table
, char *op
, int macro
,
996 const char *indent
, int lineno
)
998 char *str
, *next
, *last
;
999 bitfield types
[ARRAY_SIZE (operand_types
)];
1001 /* Copy the default operand type. */
1002 memcpy (types
, operand_types
, sizeof (types
));
1004 if (strcmp (op
, "0"))
1006 last
= op
+ strlen (op
);
1007 for (next
= op
; next
&& next
< last
; )
1009 str
= next_field (next
, '|', &next
, last
);
1011 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1014 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
1019 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1020 char *last
, int lineno
)
1023 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
1024 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1026 /* Find number of operands. */
1027 operands
= next_field (str
, ',', &str
, last
);
1029 /* Find base_opcode. */
1030 base_opcode
= next_field (str
, ',', &str
, last
);
1032 /* Find extension_opcode. */
1033 extension_opcode
= next_field (str
, ',', &str
, last
);
1035 /* Find opcode_length. */
1036 opcode_length
= next_field (str
, ',', &str
, last
);
1038 /* Find cpu_flags. */
1039 cpu_flags
= next_field (str
, ',', &str
, last
);
1041 /* Find opcode_modifier. */
1042 opcode_modifier
= next_field (str
, ',', &str
, last
);
1044 /* Remove the first {. */
1045 str
= remove_leading_whitespaces (str
);
1048 str
= remove_leading_whitespaces (str
+ 1);
1052 /* There are at least "X}". */
1056 /* Remove trailing white spaces and }. */
1060 if (ISSPACE (str
[i
]) || str
[i
] == '}')
1069 /* Find operand_types. */
1070 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1074 operand_types
[i
] = NULL
;
1078 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1079 if (*operand_types
[i
] == '0')
1082 operand_types
[i
] = NULL
;
1087 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
1088 name
, operands
, base_opcode
, extension_opcode
,
1091 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1093 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
1095 fprintf (table
, " { ");
1097 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1099 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
1102 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
1107 fprintf (table
, ",\n ");
1109 process_i386_operand_type (table
, operand_types
[i
], 0,
1112 fprintf (table
, " } },\n");
1115 struct opcode_hash_entry
1117 struct opcode_hash_entry
*next
;
1123 /* Calculate the hash value of an opcode hash entry P. */
1126 opcode_hash_hash (const void *p
)
1128 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1129 return htab_hash_string (entry
->name
);
1132 /* Compare a string Q against an opcode hash entry P. */
1135 opcode_hash_eq (const void *p
, const void *q
)
1137 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1138 const char *name
= (const char *) q
;
1139 return strcmp (name
, entry
->name
) == 0;
1143 process_i386_opcodes (FILE *table
)
1148 char *str
, *p
, *last
, *name
;
1149 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1150 htab_t opcode_hash_table
;
1151 struct opcode_hash_entry
**opcode_array
;
1152 unsigned int opcode_array_size
= 1024;
1155 filename
= "i386-opc.tbl";
1156 fp
= fopen (filename
, "r");
1159 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1163 opcode_array
= (struct opcode_hash_entry
**)
1164 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1166 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1167 opcode_hash_eq
, NULL
,
1170 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1171 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1173 /* Put everything on opcode array. */
1176 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1181 p
= remove_leading_whitespaces (buf
);
1183 /* Skip comments. */
1184 str
= strstr (p
, "//");
1188 /* Remove trailing white spaces. */
1189 remove_trailing_whitespaces (p
);
1194 /* Ignore comments. */
1202 last
= p
+ strlen (p
);
1205 name
= next_field (p
, ',', &str
, last
);
1207 /* Get the slot in hash table. */
1208 hash_slot
= (struct opcode_hash_entry
**)
1209 htab_find_slot_with_hash (opcode_hash_table
, name
,
1210 htab_hash_string (name
),
1213 if (*hash_slot
== NULL
)
1215 /* It is the new one. Put it on opcode array. */
1216 if (i
>= opcode_array_size
)
1218 /* Grow the opcode array when needed. */
1219 opcode_array_size
+= 1024;
1220 opcode_array
= (struct opcode_hash_entry
**)
1221 xrealloc (opcode_array
,
1222 sizeof (*opcode_array
) * opcode_array_size
);
1225 opcode_array
[i
] = (struct opcode_hash_entry
*)
1226 xmalloc (sizeof (struct opcode_hash_entry
));
1227 opcode_array
[i
]->next
= NULL
;
1228 opcode_array
[i
]->name
= xstrdup (name
);
1229 opcode_array
[i
]->opcode
= xstrdup (str
);
1230 opcode_array
[i
]->lineno
= lineno
;
1231 *hash_slot
= opcode_array
[i
];
1236 /* Append it to the existing one. */
1238 while ((*entry
) != NULL
)
1239 entry
= &(*entry
)->next
;
1240 *entry
= (struct opcode_hash_entry
*)
1241 xmalloc (sizeof (struct opcode_hash_entry
));
1242 (*entry
)->next
= NULL
;
1243 (*entry
)->name
= (*hash_slot
)->name
;
1244 (*entry
)->opcode
= xstrdup (str
);
1245 (*entry
)->lineno
= lineno
;
1249 /* Process opcode array. */
1250 for (j
= 0; j
< i
; j
++)
1252 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1256 lineno
= next
->lineno
;
1257 last
= str
+ strlen (str
);
1258 output_i386_opcode (table
, name
, str
, last
, lineno
);
1264 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1266 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1268 process_i386_opcode_modifier (table
, "0", -1);
1270 fprintf (table
, " { ");
1271 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1272 fprintf (table
, " } }\n");
1274 fprintf (table
, "};\n");
1278 process_i386_registers (FILE *table
)
1282 char *str
, *p
, *last
;
1283 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1284 char *dw2_32_num
, *dw2_64_num
;
1287 filename
= "i386-reg.tbl";
1288 fp
= fopen (filename
, "r");
1290 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1293 fprintf (table
, "\n/* i386 register table. */\n\n");
1294 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1298 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1303 p
= remove_leading_whitespaces (buf
);
1305 /* Skip comments. */
1306 str
= strstr (p
, "//");
1310 /* Remove trailing white spaces. */
1311 remove_trailing_whitespaces (p
);
1316 fprintf (table
, "%s\n", p
);
1324 last
= p
+ strlen (p
);
1326 /* Find reg_name. */
1327 reg_name
= next_field (p
, ',', &str
, last
);
1329 /* Find reg_type. */
1330 reg_type
= next_field (str
, ',', &str
, last
);
1332 /* Find reg_flags. */
1333 reg_flags
= next_field (str
, ',', &str
, last
);
1336 reg_num
= next_field (str
, ',', &str
, last
);
1338 fprintf (table
, " { \"%s\",\n ", reg_name
);
1340 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1342 /* Find 32-bit Dwarf2 register number. */
1343 dw2_32_num
= next_field (str
, ',', &str
, last
);
1345 /* Find 64-bit Dwarf2 register number. */
1346 dw2_64_num
= next_field (str
, ',', &str
, last
);
1348 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1349 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1354 fprintf (table
, "};\n");
1356 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1360 process_i386_initializers (void)
1363 FILE *fp
= fopen ("i386-init.h", "w");
1367 fail (_("can't create i386-init.h, errno = %s\n"),
1370 process_copyright (fp
);
1372 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1374 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1375 init
= xstrdup (cpu_flag_init
[i
].init
);
1376 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1380 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1382 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1383 init
= xstrdup (operand_type_init
[i
].init
);
1384 process_i386_operand_type (fp
, init
, 1, " ", -1);
1392 /* Program options. */
1393 #define OPTION_SRCDIR 200
1395 struct option long_options
[] =
1397 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1398 {"debug", no_argument
, NULL
, 'd'},
1399 {"version", no_argument
, NULL
, 'V'},
1400 {"help", no_argument
, NULL
, 'h'},
1401 {0, no_argument
, NULL
, 0}
1405 print_version (void)
1407 printf ("%s: version 1.0\n", program_name
);
1412 usage (FILE * stream
, int status
)
1414 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1420 main (int argc
, char **argv
)
1422 extern int chdir (char *);
1423 char *srcdir
= NULL
;
1425 unsigned int i
, cpumax
;
1428 program_name
= *argv
;
1429 xmalloc_set_program_name (program_name
);
1431 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1456 if (chdir (srcdir
) != 0)
1457 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1458 srcdir
, xstrerror (errno
));
1460 /* cpu_flags isn't sorted by position. */
1462 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1463 if (cpu_flags
[i
].position
> cpumax
)
1464 cpumax
= cpu_flags
[i
].position
;
1466 /* Check the unused bitfield in i386_cpu_flags. */
1468 if ((cpumax
- 1) != CpuMax
)
1469 fail (_("CpuMax != %d!\n"), cpumax
);
1471 if (cpumax
!= CpuMax
)
1472 fail (_("CpuMax != %d!\n"), cpumax
);
1474 c
= CpuNumOfBits
- CpuMax
- 1;
1476 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1479 /* Check the unused bitfield in i386_operand_type. */
1481 c
= OTNumOfBits
- OTMax
- 1;
1483 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1486 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1489 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1490 sizeof (opcode_modifiers
[0]), compare
);
1492 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1493 sizeof (operand_types
[0]), compare
);
1495 table
= fopen ("i386-tbl.h", "w");
1497 fail (_("can't create i386-tbl.h, errno = %s\n"),
1500 process_copyright (table
);
1502 process_i386_opcodes (table
);
1503 process_i386_registers (table
);
1504 process_i386_initializers ();