1 /* Copyright (C) 2007-2014 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 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuLM" },
57 "Cpu186|Cpu286|Cpu386" },
59 "Cpu186|Cpu286|Cpu386|Cpu486" },
61 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu387" },
63 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687" },
64 { "CPU_PENTIUMPRO_FLAGS",
65 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop" },
67 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX" },
69 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE" },
71 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2" },
73 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM|CpuCX16" },
75 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuCX16" },
77 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM|CpuCX16" },
79 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuRdtscp|CpuLM|CpuCX16" },
81 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX" },
83 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX|Cpu3dnow" },
85 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA" },
87 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
88 { "CPU_AMDFAM10_FLAGS",
89 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
91 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA4|CpuXOP|CpuLWP|CpuCX16|CpuClflush|CpuSSSE3|CpuSVME|CpuSSE4_1|CpuSSE4_2|CpuXsave|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW" },
93 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA|CpuFMA4|CpuXOP|CpuLWP|CpuBMI|CpuTBM|CpuF16C|CpuCX16|CpuClflush|CpuSSSE3|CpuSVME|CpuSSE4_1|CpuSSE4_2|CpuXsave|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW" },
95 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA|CpuFMA4|CpuXOP|CpuLWP|CpuBMI|CpuTBM|CpuF16C|CpuCX16|CpuClflush|CpuSSSE3|CpuSVME|CpuSSE4_1|CpuSSE4_2|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW|CpuXsave|CpuXsaveopt|CpuFSGSBase" },
97 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA|CpuFMA4|CpuXOP|CpuLWP|CpuBMI|CpuTBM|CpuF16C|CpuCX16|CpuClflush|CpuSSSE3|CpuSVME|CpuSSE4_1|CpuSSE4_2|CpuAES|CpuAVX|CpuPCLMUL|CpuLZCNT|CpuPRFCHW|CpuXsave|CpuXsaveopt|CpuFSGSBase|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd" },
99 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4a|CpuABM|CpuLM|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME|CpuLZCNT" },
100 { "CPU_BTVER2_FLAGS",
101 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4a|CpuSSE4_1|CpuSSE4_2|CpuABM|CpuLM|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuAVX|CpuMovbe|CpuXsave|CpuXsaveopt|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME|CpuLZCNT" },
109 "Cpu8087|Cpu287|Cpu387|Cpu687|CpuFISTTP" },
110 { "CPU_CLFLUSH_FLAGS",
114 { "CPU_SYSCALL_FLAGS",
121 "CpuMMX|CpuSSE|CpuSSE2" },
123 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
125 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
126 { "CPU_SSE4_1_FLAGS",
127 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
128 { "CPU_SSE4_2_FLAGS",
129 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
130 { "CPU_ANY_SSE_FLAGS",
131 "CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF" },
138 { "CPU_XSAVEOPT_FLAGS",
141 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
142 { "CPU_PCLMUL_FLAGS",
143 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
145 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
147 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA4" },
149 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP" },
160 { "CPU_RDTSCP_FLAGS",
164 { "CPU_FSGSBASE_FLAGS",
178 { "CPU_INVPCID_FLAGS",
180 { "CPU_VMFUNC_FLAGS",
184 { "CPU_3DNOWA_FLAGS",
185 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
186 { "CPU_PADLOCK_FLAGS",
191 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
195 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
197 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2" },
198 { "CPU_AVX512F_FLAGS",
199 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F" },
200 { "CPU_AVX512CD_FLAGS",
201 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512CD" },
202 { "CPU_AVX512ER_FLAGS",
203 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512ER" },
204 { "CPU_AVX512PF_FLAGS",
205 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512PF" },
206 { "CPU_ANY_AVX_FLAGS",
207 "CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF" },
214 { "CPU_RDSEED_FLAGS",
216 { "CPU_PRFCHW_FLAGS",
224 { "CPU_CLFLUSHOPT_FLAGS",
226 { "CPU_XSAVES_FLAGS",
228 { "CPU_XSAVEC_FLAGS",
230 { "CPU_PREFETCHWT1_FLAGS",
234 { "CPU_AVX512DQ_FLAGS",
235 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512DQ" },
236 { "CPU_AVX512BW_FLAGS",
237 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512BW" },
238 { "CPU_AVX512VL_FLAGS",
239 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512VL" },
242 static initializer operand_type_init[] =
244 { "OPERAND_TYPE_NONE",
246 { "OPERAND_TYPE_REG8",
248 { "OPERAND_TYPE_REG16",
250 { "OPERAND_TYPE_REG32",
252 { "OPERAND_TYPE_REG64",
254 { "OPERAND_TYPE_IMM1",
256 { "OPERAND_TYPE_IMM8",
258 { "OPERAND_TYPE_IMM8S",
260 { "OPERAND_TYPE_IMM16",
262 { "OPERAND_TYPE_IMM32",
264 { "OPERAND_TYPE_IMM32S",
266 { "OPERAND_TYPE_IMM64",
268 { "OPERAND_TYPE_BASEINDEX",
270 { "OPERAND_TYPE_DISP8",
272 { "OPERAND_TYPE_DISP16",
274 { "OPERAND_TYPE_DISP32",
276 { "OPERAND_TYPE_DISP32S",
278 { "OPERAND_TYPE_DISP64",
280 { "OPERAND_TYPE_INOUTPORTREG",
282 { "OPERAND_TYPE_SHIFTCOUNT",
284 { "OPERAND_TYPE_CONTROL",
286 { "OPERAND_TYPE_TEST",
288 { "OPERAND_TYPE_DEBUG",
290 { "OPERAND_TYPE_FLOATREG",
292 { "OPERAND_TYPE_FLOATACC",
294 { "OPERAND_TYPE_SREG2",
296 { "OPERAND_TYPE_SREG3",
298 { "OPERAND_TYPE_ACC",
300 { "OPERAND_TYPE_JUMPABSOLUTE",
302 { "OPERAND_TYPE_REGMMX",
304 { "OPERAND_TYPE_REGXMM",
306 { "OPERAND_TYPE_REGYMM",
308 { "OPERAND_TYPE_REGZMM",
310 { "OPERAND_TYPE_REGMASK",
312 { "OPERAND_TYPE_ESSEG",
314 { "OPERAND_TYPE_ACC32",
316 { "OPERAND_TYPE_ACC64",
318 { "OPERAND_TYPE_INOUTPORTREG",
320 { "OPERAND_TYPE_REG16_INOUTPORTREG",
321 "Reg16|InOutPortReg" },
322 { "OPERAND_TYPE_DISP16_32",
324 { "OPERAND_TYPE_ANYDISP",
325 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
326 { "OPERAND_TYPE_IMM16_32",
328 { "OPERAND_TYPE_IMM16_32S",
330 { "OPERAND_TYPE_IMM16_32_32S",
331 "Imm16|Imm32|Imm32S" },
332 { "OPERAND_TYPE_IMM32_64",
334 { "OPERAND_TYPE_IMM32_32S_DISP32",
335 "Imm32|Imm32S|Disp32" },
336 { "OPERAND_TYPE_IMM64_DISP64",
338 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
339 "Imm32|Imm32S|Imm64|Disp32" },
340 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
341 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
342 { "OPERAND_TYPE_VEC_IMM4",
344 { "OPERAND_TYPE_REGBND",
346 { "OPERAND_TYPE_VEC_DISP8",
350 typedef struct bitfield
357 #define BITFIELD(n) { n, 0, #n }
359 static bitfield cpu_flags[] =
367 BITFIELD (CpuClflush),
369 BITFIELD (CpuSYSCALL),
374 BITFIELD (CpuFISTTP),
380 BITFIELD (CpuSSE4_1),
381 BITFIELD (CpuSSE4_2),
384 BITFIELD (CpuAVX512F),
385 BITFIELD (CpuAVX512CD),
386 BITFIELD (CpuAVX512ER),
387 BITFIELD (CpuAVX512PF),
388 BITFIELD (CpuAVX512VL),
389 BITFIELD (CpuAVX512DQ),
390 BITFIELD (CpuAVX512BW),
395 BITFIELD (Cpu3dnowA),
396 BITFIELD (CpuPadLock),
402 BITFIELD (CpuXsaveopt),
404 BITFIELD (CpuPCLMUL),
415 BITFIELD (CpuRdtscp),
416 BITFIELD (CpuFSGSBase),
423 BITFIELD (CpuINVPCID),
424 BITFIELD (CpuVMFUNC),
425 BITFIELD (CpuRDSEED),
427 BITFIELD (CpuPRFCHW),
431 BITFIELD (CpuClflushOpt),
432 BITFIELD (CpuXSAVES),
433 BITFIELD (CpuXSAVEC),
434 BITFIELD (CpuPREFETCHWT1),
440 BITFIELD (CpuUnused),
444 static bitfield opcode_modifiers[] =
450 BITFIELD (ShortForm),
452 BITFIELD (JumpDword),
454 BITFIELD (JumpInterSegment),
461 BITFIELD (CheckRegSize),
462 BITFIELD (IgnoreSize),
463 BITFIELD (DefaultSize),
472 BITFIELD (BNDPrefixOk),
473 BITFIELD (IsLockable),
474 BITFIELD (RegKludge),
475 BITFIELD (FirstXmm0),
476 BITFIELD (Implicit1stXmm0),
477 BITFIELD (RepPrefixOk),
478 BITFIELD (HLEPrefixOk),
481 BITFIELD (AddrPrefixOp0),
490 BITFIELD (VexOpcode),
491 BITFIELD (VexSources),
492 BITFIELD (VexImmExt),
499 BITFIELD (Broadcast),
500 BITFIELD (StaticRounding),
502 BITFIELD (Disp8MemShift),
503 BITFIELD (NoDefMask),
505 BITFIELD (ATTMnemonic),
506 BITFIELD (ATTSyntax),
507 BITFIELD (IntelSyntax),
510 static bitfield operand_types[] =
529 BITFIELD (BaseIndex),
535 BITFIELD (InOutPortReg),
536 BITFIELD (ShiftCount),
544 BITFIELD (JumpAbsolute),
557 BITFIELD (Unspecified),
561 BITFIELD (Vec_Disp8),
567 static const char *filename;
570 compare (const void *x, const void *y)
572 const bitfield *xp = (const bitfield *) x;
573 const bitfield *yp = (const bitfield *) y;
574 return xp->position - yp->position;
578 fail (const char *message, ...)
582 va_start (args, message);
583 fprintf (stderr, _("%s: Error: "), program_name);
584 vfprintf (stderr, message, args);
590 process_copyright (FILE *fp)
592 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
593 /* Copyright (C) 2007-2014 Free Software Foundation, Inc.\n\
595 This file is part of the GNU opcodes library.\n\
597 This library is free software; you can redistribute it and/or modify\n\
598 it under the terms of the GNU General Public License as published by\n\
599 the Free Software Foundation; either version 3, or (at your option)\n\
600 any later version.\n\
602 It is distributed in the hope that it will be useful, but WITHOUT\n\
603 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
604 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
605 License for more details.\n\
607 You should have received a copy of the GNU General Public License\n\
608 along with this program; if not, write to the Free Software\n\
609 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
610 MA 02110-1301, USA. */\n");
613 /* Remove leading white spaces. */
616 remove_leading_whitespaces (char *str)
618 while (ISSPACE (*str))
623 /* Remove trailing white spaces. */
626 remove_trailing_whitespaces (char *str)
628 size_t last = strlen (str);
636 if (ISSPACE (str [last]))
644 /* Find next field separated by SEP and terminate it. Return a
645 pointer to the one after it. */
648 next_field (char *str, char sep, char **next, char *last)
652 p = remove_leading_whitespaces (str);
653 for (str = p; *str != sep && *str != '\0'; str++);
656 remove_trailing_whitespaces (p);
667 set_bitfield (const char *f, bitfield *array, int value,
668 unsigned int size, int lineno)
672 if (strcmp (f, "CpuFP") == 0)
674 set_bitfield("Cpu387", array, value, size, lineno);
675 set_bitfield("Cpu287", array, value, size, lineno);
678 else if (strcmp (f, "Mmword") == 0)
680 else if (strcmp (f, "Oword") == 0)
683 for (i = 0; i < size; i++)
684 if (strcasecmp (array[i].name, f) == 0)
686 array[i].value = value;
692 const char *v = strchr (f, '=');
699 for (i = 0; i < size; i++)
700 if (strncasecmp (array[i].name, f, n) == 0)
702 value = strtol (v + 1, &end, 0);
705 array[i].value = value;
714 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
716 fail (_("Unknown bitfield: %s\n"), f);
720 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
721 int macro, const char *comma, const char *indent)
725 fprintf (table, "%s{ { ", indent);
727 for (i = 0; i < size - 1; i++)
729 if (((i + 1) % 20) != 0)
730 fprintf (table, "%d, ", flags[i].value);
732 fprintf (table, "%d,", flags[i].value);
733 if (((i + 1) % 20) == 0)
735 /* We need \\ for macro. */
737 fprintf (table, " \\\n %s", indent);
739 fprintf (table, "\n %s", indent);
743 fprintf (table, "%d } }%s\n", flags[i].value, comma);
747 process_i386_cpu_flag (FILE *table, char *flag, int macro,
748 const char *comma, const char *indent,
751 char *str, *next, *last;
753 bitfield flags [ARRAY_SIZE (cpu_flags)];
755 /* Copy the default cpu flags. */
756 memcpy (flags, cpu_flags, sizeof (cpu_flags));
758 if (strcasecmp (flag, "unknown") == 0)
760 /* We turn on everything except for cpu64 in case of
761 CPU_UNKNOWN_FLAGS. */
762 for (i = 0; i < ARRAY_SIZE (flags); i++)
763 if (flags[i].position != Cpu64)
766 else if (flag[0] == '~')
768 last = flag + strlen (flag);
775 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
782 /* First we turn on everything except for cpu64. */
783 for (i = 0; i < ARRAY_SIZE (flags); i++)
784 if (flags[i].position != Cpu64)
787 /* Turn off selective bits. */
788 for (; next && next < last; )
790 str = next_field (next, '|', &next, last);
792 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
795 else if (strcmp (flag, "0"))
797 /* Turn on selective bits. */
798 last = flag + strlen (flag);
799 for (next = flag; next && next < last; )
801 str = next_field (next, '|', &next, last);
803 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
807 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
812 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
816 fprintf (table, " { ");
818 for (i = 0; i < size - 1; i++)
820 if (((i + 1) % 20) != 0)
821 fprintf (table, "%d, ", modifier[i].value);
823 fprintf (table, "%d,", modifier[i].value);
824 if (((i + 1) % 20) == 0)
825 fprintf (table, "\n ");
828 fprintf (table, "%d },\n", modifier[i].value);
832 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
834 char *str, *next, *last;
835 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
837 /* Copy the default opcode modifier. */
838 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
840 if (strcmp (mod, "0"))
842 last = mod + strlen (mod);
843 for (next = mod; next && next < last; )
845 str = next_field (next, '|', &next, last);
847 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
851 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
855 output_operand_type (FILE *table, bitfield *types, unsigned int size,
856 int macro, const char *indent)
860 fprintf (table, "{ { ");
862 for (i = 0; i < size - 1; i++)
864 if (((i + 1) % 20) != 0)
865 fprintf (table, "%d, ", types[i].value);
867 fprintf (table, "%d,", types[i].value);
868 if (((i + 1) % 20) == 0)
870 /* We need \\ for macro. */
872 fprintf (table, " \\\n%s", indent);
874 fprintf (table, "\n%s", indent);
878 fprintf (table, "%d } }", types[i].value);
882 process_i386_operand_type (FILE *table, char *op, int macro,
883 const char *indent, int lineno)
885 char *str, *next, *last;
886 bitfield types [ARRAY_SIZE (operand_types)];
888 /* Copy the default operand type. */
889 memcpy (types, operand_types, sizeof (types));
891 if (strcmp (op, "0"))
893 last = op + strlen (op);
894 for (next = op; next && next < last; )
896 str = next_field (next, '|', &next, last);
898 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
901 output_operand_type (table, types, ARRAY_SIZE (types), macro,
906 output_i386_opcode (FILE *table, const char *name, char *str,
907 char *last, int lineno)
910 char *operands, *base_opcode, *extension_opcode, *opcode_length;
911 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
913 /* Find number of operands. */
914 operands = next_field (str, ',', &str, last);
916 /* Find base_opcode. */
917 base_opcode = next_field (str, ',', &str, last);
919 /* Find extension_opcode. */
920 extension_opcode = next_field (str, ',', &str, last);
922 /* Find opcode_length. */
923 opcode_length = next_field (str, ',', &str, last);
925 /* Find cpu_flags. */
926 cpu_flags = next_field (str, ',', &str, last);
928 /* Find opcode_modifier. */
929 opcode_modifier = next_field (str, ',', &str, last);
931 /* Remove the first {. */
932 str = remove_leading_whitespaces (str);
935 str = remove_leading_whitespaces (str + 1);
939 /* There are at least "X}". */
943 /* Remove trailing white spaces and }. */
947 if (ISSPACE (str[i]) || str[i] == '}')
956 /* Find operand_types. */
957 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
961 operand_types [i] = NULL;
965 operand_types [i] = next_field (str, ',', &str, last);
966 if (*operand_types[i] == '0')
969 operand_types[i] = NULL;
974 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
975 name, operands, base_opcode, extension_opcode,
978 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
980 process_i386_opcode_modifier (table, opcode_modifier, lineno);
982 fprintf (table, " { ");
984 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
986 if (operand_types[i] == NULL || *operand_types[i] == '0')
989 process_i386_operand_type (table, "0", 0, "\t ", lineno);
994 fprintf (table, ",\n ");
996 process_i386_operand_type (table, operand_types[i], 0,
999 fprintf (table, " } },\n");
1002 struct opcode_hash_entry
1004 struct opcode_hash_entry *next;
1010 /* Calculate the hash value of an opcode hash entry P. */
1013 opcode_hash_hash (const void *p)
1015 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1016 return htab_hash_string (entry->name);
1019 /* Compare a string Q against an opcode hash entry P. */
1022 opcode_hash_eq (const void *p, const void *q)
1024 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1025 const char *name = (const char *) q;
1026 return strcmp (name, entry->name) == 0;
1030 process_i386_opcodes (FILE *table)
1035 char *str, *p, *last, *name;
1036 struct opcode_hash_entry **hash_slot, **entry, *next;
1037 htab_t opcode_hash_table;
1038 struct opcode_hash_entry **opcode_array;
1039 unsigned int opcode_array_size = 1024;
1042 filename = "i386-opc.tbl";
1043 fp = fopen (filename, "r");
1046 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1050 opcode_array = (struct opcode_hash_entry **)
1051 xmalloc (sizeof (*opcode_array) * opcode_array_size);
1053 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1054 opcode_hash_eq, NULL,
1057 fprintf (table, "\n/* i386 opcode table. */\n\n");
1058 fprintf (table, "const insn_template i386_optab[] =\n{\n");
1060 /* Put everything on opcode array. */
1063 if (fgets (buf, sizeof (buf), fp) == NULL)
1068 p = remove_leading_whitespaces (buf);
1070 /* Skip comments. */
1071 str = strstr (p, "//");
1075 /* Remove trailing white spaces. */
1076 remove_trailing_whitespaces (p);
1081 /* Ignore comments. */
1089 last = p + strlen (p);
1092 name = next_field (p, ',', &str, last);
1094 /* Get the slot in hash table. */
1095 hash_slot = (struct opcode_hash_entry **)
1096 htab_find_slot_with_hash (opcode_hash_table, name,
1097 htab_hash_string (name),
1100 if (*hash_slot == NULL)
1102 /* It is the new one. Put it on opcode array. */
1103 if (i >= opcode_array_size)
1105 /* Grow the opcode array when needed. */
1106 opcode_array_size += 1024;
1107 opcode_array = (struct opcode_hash_entry **)
1108 xrealloc (opcode_array,
1109 sizeof (*opcode_array) * opcode_array_size);
1112 opcode_array[i] = (struct opcode_hash_entry *)
1113 xmalloc (sizeof (struct opcode_hash_entry));
1114 opcode_array[i]->next = NULL;
1115 opcode_array[i]->name = xstrdup (name);
1116 opcode_array[i]->opcode = xstrdup (str);
1117 opcode_array[i]->lineno = lineno;
1118 *hash_slot = opcode_array[i];
1123 /* Append it to the existing one. */
1125 while ((*entry) != NULL)
1126 entry = &(*entry)->next;
1127 *entry = (struct opcode_hash_entry *)
1128 xmalloc (sizeof (struct opcode_hash_entry));
1129 (*entry)->next = NULL;
1130 (*entry)->name = (*hash_slot)->name;
1131 (*entry)->opcode = xstrdup (str);
1132 (*entry)->lineno = lineno;
1136 /* Process opcode array. */
1137 for (j = 0; j < i; j++)
1139 for (next = opcode_array[j]; next; next = next->next)
1143 lineno = next->lineno;
1144 last = str + strlen (str);
1145 output_i386_opcode (table, name, str, last, lineno);
1151 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1153 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1155 process_i386_opcode_modifier (table, "0", -1);
1157 fprintf (table, " { ");
1158 process_i386_operand_type (table, "0", 0, "\t ", -1);
1159 fprintf (table, " } }\n");
1161 fprintf (table, "};\n");
1165 process_i386_registers (FILE *table)
1169 char *str, *p, *last;
1170 char *reg_name, *reg_type, *reg_flags, *reg_num;
1171 char *dw2_32_num, *dw2_64_num;
1174 filename = "i386-reg.tbl";
1175 fp = fopen (filename, "r");
1177 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1180 fprintf (table, "\n/* i386 register table. */\n\n");
1181 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1185 if (fgets (buf, sizeof (buf), fp) == NULL)
1190 p = remove_leading_whitespaces (buf);
1192 /* Skip comments. */
1193 str = strstr (p, "//");
1197 /* Remove trailing white spaces. */
1198 remove_trailing_whitespaces (p);
1203 fprintf (table, "%s\n", p);
1211 last = p + strlen (p);
1213 /* Find reg_name. */
1214 reg_name = next_field (p, ',', &str, last);
1216 /* Find reg_type. */
1217 reg_type = next_field (str, ',', &str, last);
1219 /* Find reg_flags. */
1220 reg_flags = next_field (str, ',', &str, last);
1223 reg_num = next_field (str, ',', &str, last);
1225 fprintf (table, " { \"%s\",\n ", reg_name);
1227 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1229 /* Find 32-bit Dwarf2 register number. */
1230 dw2_32_num = next_field (str, ',', &str, last);
1232 /* Find 64-bit Dwarf2 register number. */
1233 dw2_64_num = next_field (str, ',', &str, last);
1235 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1236 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1241 fprintf (table, "};\n");
1243 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1247 process_i386_initializers (void)
1250 FILE *fp = fopen ("i386-init.h", "w");
1254 fail (_("can't create i386-init.h, errno = %s\n"),
1257 process_copyright (fp);
1259 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1261 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1262 init = xstrdup (cpu_flag_init[i].init);
1263 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1267 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1269 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1270 init = xstrdup (operand_type_init[i].init);
1271 process_i386_operand_type (fp, init, 1, " ", -1);
1279 /* Program options. */
1280 #define OPTION_SRCDIR 200
1282 struct option long_options[] =
1284 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1285 {"debug", no_argument, NULL, 'd'},
1286 {"version", no_argument, NULL, 'V'},
1287 {"help", no_argument, NULL, 'h'},
1288 {0, no_argument, NULL, 0}
1292 print_version (void)
1294 printf ("%s: version 1.0\n", program_name);
1299 usage (FILE * stream, int status)
1301 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1307 main (int argc, char **argv)
1309 extern int chdir (char *);
1310 char *srcdir = NULL;
1314 program_name = *argv;
1315 xmalloc_set_program_name (program_name);
1317 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1342 if (chdir (srcdir) != 0)
1343 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1344 srcdir, xstrerror (errno));
1346 /* Check the unused bitfield in i386_cpu_flags. */
1348 c = CpuNumOfBits - CpuMax - 1;
1350 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1353 /* Check the unused bitfield in i386_operand_type. */
1355 c = OTNumOfBits - OTMax - 1;
1357 fail (_("%d unused bits in i386_operand_type.\n"), c);
1360 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1363 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1364 sizeof (opcode_modifiers [0]), compare);
1366 qsort (operand_types, ARRAY_SIZE (operand_types),
1367 sizeof (operand_types [0]), compare);
1369 table = fopen ("i386-tbl.h", "w");
1371 fail (_("can't create i386-tbl.h, errno = %s\n"),
1374 process_copyright (table);
1376 process_i386_opcodes (table);
1377 process_i386_registers (table);
1378 process_i386_initializers ();