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",
236 static initializer operand_type_init
[] =
238 { "OPERAND_TYPE_NONE",
240 { "OPERAND_TYPE_REG8",
242 { "OPERAND_TYPE_REG16",
244 { "OPERAND_TYPE_REG32",
246 { "OPERAND_TYPE_REG64",
248 { "OPERAND_TYPE_IMM1",
250 { "OPERAND_TYPE_IMM8",
252 { "OPERAND_TYPE_IMM8S",
254 { "OPERAND_TYPE_IMM16",
256 { "OPERAND_TYPE_IMM32",
258 { "OPERAND_TYPE_IMM32S",
260 { "OPERAND_TYPE_IMM64",
262 { "OPERAND_TYPE_BASEINDEX",
264 { "OPERAND_TYPE_DISP8",
266 { "OPERAND_TYPE_DISP16",
268 { "OPERAND_TYPE_DISP32",
270 { "OPERAND_TYPE_DISP32S",
272 { "OPERAND_TYPE_DISP64",
274 { "OPERAND_TYPE_INOUTPORTREG",
276 { "OPERAND_TYPE_SHIFTCOUNT",
278 { "OPERAND_TYPE_CONTROL",
280 { "OPERAND_TYPE_TEST",
282 { "OPERAND_TYPE_DEBUG",
284 { "OPERAND_TYPE_FLOATREG",
286 { "OPERAND_TYPE_FLOATACC",
288 { "OPERAND_TYPE_SREG2",
290 { "OPERAND_TYPE_SREG3",
292 { "OPERAND_TYPE_ACC",
294 { "OPERAND_TYPE_JUMPABSOLUTE",
296 { "OPERAND_TYPE_REGMMX",
298 { "OPERAND_TYPE_REGXMM",
300 { "OPERAND_TYPE_REGYMM",
302 { "OPERAND_TYPE_REGZMM",
304 { "OPERAND_TYPE_REGMASK",
306 { "OPERAND_TYPE_ESSEG",
308 { "OPERAND_TYPE_ACC32",
310 { "OPERAND_TYPE_ACC64",
312 { "OPERAND_TYPE_INOUTPORTREG",
314 { "OPERAND_TYPE_REG16_INOUTPORTREG",
315 "Reg16|InOutPortReg" },
316 { "OPERAND_TYPE_DISP16_32",
318 { "OPERAND_TYPE_ANYDISP",
319 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
320 { "OPERAND_TYPE_IMM16_32",
322 { "OPERAND_TYPE_IMM16_32S",
324 { "OPERAND_TYPE_IMM16_32_32S",
325 "Imm16|Imm32|Imm32S" },
326 { "OPERAND_TYPE_IMM32_64",
328 { "OPERAND_TYPE_IMM32_32S_DISP32",
329 "Imm32|Imm32S|Disp32" },
330 { "OPERAND_TYPE_IMM64_DISP64",
332 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
333 "Imm32|Imm32S|Imm64|Disp32" },
334 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
335 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
336 { "OPERAND_TYPE_VEC_IMM4",
338 { "OPERAND_TYPE_REGBND",
340 { "OPERAND_TYPE_VEC_DISP8",
344 typedef struct bitfield
351 #define BITFIELD(n) { n, 0, #n }
353 static bitfield cpu_flags
[] =
361 BITFIELD (CpuClflush
),
363 BITFIELD (CpuSYSCALL
),
368 BITFIELD (CpuFISTTP
),
374 BITFIELD (CpuSSE4_1
),
375 BITFIELD (CpuSSE4_2
),
378 BITFIELD (CpuAVX512F
),
379 BITFIELD (CpuAVX512CD
),
380 BITFIELD (CpuAVX512ER
),
381 BITFIELD (CpuAVX512PF
),
386 BITFIELD (Cpu3dnowA
),
387 BITFIELD (CpuPadLock
),
393 BITFIELD (CpuXsaveopt
),
395 BITFIELD (CpuPCLMUL
),
406 BITFIELD (CpuRdtscp
),
407 BITFIELD (CpuFSGSBase
),
414 BITFIELD (CpuINVPCID
),
415 BITFIELD (CpuVMFUNC
),
416 BITFIELD (CpuRDSEED
),
418 BITFIELD (CpuPRFCHW
),
422 BITFIELD (CpuClflushOpt
),
423 BITFIELD (CpuXSAVES
),
424 BITFIELD (CpuXSAVEC
),
425 BITFIELD (CpuPREFETCHWT1
),
431 BITFIELD (CpuUnused
),
435 static bitfield opcode_modifiers
[] =
441 BITFIELD (ShortForm
),
443 BITFIELD (JumpDword
),
445 BITFIELD (JumpInterSegment
),
452 BITFIELD (CheckRegSize
),
453 BITFIELD (IgnoreSize
),
454 BITFIELD (DefaultSize
),
463 BITFIELD (BNDPrefixOk
),
464 BITFIELD (IsLockable
),
465 BITFIELD (RegKludge
),
466 BITFIELD (FirstXmm0
),
467 BITFIELD (Implicit1stXmm0
),
468 BITFIELD (RepPrefixOk
),
469 BITFIELD (HLEPrefixOk
),
472 BITFIELD (AddrPrefixOp0
),
481 BITFIELD (VexOpcode
),
482 BITFIELD (VexSources
),
483 BITFIELD (VexImmExt
),
490 BITFIELD (Broadcast
),
491 BITFIELD (StaticRounding
),
493 BITFIELD (Disp8MemShift
),
494 BITFIELD (NoDefMask
),
496 BITFIELD (ATTMnemonic
),
497 BITFIELD (ATTSyntax
),
498 BITFIELD (IntelSyntax
),
501 static bitfield operand_types
[] =
520 BITFIELD (BaseIndex
),
526 BITFIELD (InOutPortReg
),
527 BITFIELD (ShiftCount
),
535 BITFIELD (JumpAbsolute
),
548 BITFIELD (Unspecified
),
552 BITFIELD (Vec_Disp8
),
558 static const char *filename
;
561 compare (const void *x
, const void *y
)
563 const bitfield
*xp
= (const bitfield
*) x
;
564 const bitfield
*yp
= (const bitfield
*) y
;
565 return xp
->position
- yp
->position
;
569 fail (const char *message
, ...)
573 va_start (args
, message
);
574 fprintf (stderr
, _("%s: Error: "), program_name
);
575 vfprintf (stderr
, message
, args
);
581 process_copyright (FILE *fp
)
583 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
584 /* Copyright (C) 2007-2014 Free Software Foundation, Inc.\n\
586 This file is part of the GNU opcodes library.\n\
588 This library is free software; you can redistribute it and/or modify\n\
589 it under the terms of the GNU General Public License as published by\n\
590 the Free Software Foundation; either version 3, or (at your option)\n\
591 any later version.\n\
593 It is distributed in the hope that it will be useful, but WITHOUT\n\
594 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
595 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
596 License for more details.\n\
598 You should have received a copy of the GNU General Public License\n\
599 along with this program; if not, write to the Free Software\n\
600 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
601 MA 02110-1301, USA. */\n");
604 /* Remove leading white spaces. */
607 remove_leading_whitespaces (char *str
)
609 while (ISSPACE (*str
))
614 /* Remove trailing white spaces. */
617 remove_trailing_whitespaces (char *str
)
619 size_t last
= strlen (str
);
627 if (ISSPACE (str
[last
]))
635 /* Find next field separated by SEP and terminate it. Return a
636 pointer to the one after it. */
639 next_field (char *str
, char sep
, char **next
, char *last
)
643 p
= remove_leading_whitespaces (str
);
644 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
647 remove_trailing_whitespaces (p
);
658 set_bitfield (const char *f
, bitfield
*array
, int value
,
659 unsigned int size
, int lineno
)
663 if (strcmp (f
, "CpuFP") == 0)
665 set_bitfield("Cpu387", array
, value
, size
, lineno
);
666 set_bitfield("Cpu287", array
, value
, size
, lineno
);
669 else if (strcmp (f
, "Mmword") == 0)
671 else if (strcmp (f
, "Oword") == 0)
674 for (i
= 0; i
< size
; i
++)
675 if (strcasecmp (array
[i
].name
, f
) == 0)
677 array
[i
].value
= value
;
683 const char *v
= strchr (f
, '=');
690 for (i
= 0; i
< size
; i
++)
691 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
693 value
= strtol (v
+ 1, &end
, 0);
696 array
[i
].value
= value
;
705 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
707 fail (_("Unknown bitfield: %s\n"), f
);
711 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
712 int macro
, const char *comma
, const char *indent
)
716 fprintf (table
, "%s{ { ", indent
);
718 for (i
= 0; i
< size
- 1; i
++)
720 if (((i
+ 1) % 20) != 0)
721 fprintf (table
, "%d, ", flags
[i
].value
);
723 fprintf (table
, "%d,", flags
[i
].value
);
724 if (((i
+ 1) % 20) == 0)
726 /* We need \\ for macro. */
728 fprintf (table
, " \\\n %s", indent
);
730 fprintf (table
, "\n %s", indent
);
734 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
738 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
739 const char *comma
, const char *indent
,
742 char *str
, *next
, *last
;
744 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
746 /* Copy the default cpu flags. */
747 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
749 if (strcasecmp (flag
, "unknown") == 0)
751 /* We turn on everything except for cpu64 in case of
752 CPU_UNKNOWN_FLAGS. */
753 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
754 if (flags
[i
].position
!= Cpu64
)
757 else if (flag
[0] == '~')
759 last
= flag
+ strlen (flag
);
766 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
773 /* First we turn on everything except for cpu64. */
774 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
775 if (flags
[i
].position
!= Cpu64
)
778 /* Turn off selective bits. */
779 for (; next
&& next
< last
; )
781 str
= next_field (next
, '|', &next
, last
);
783 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
786 else if (strcmp (flag
, "0"))
788 /* Turn on selective bits. */
789 last
= flag
+ strlen (flag
);
790 for (next
= flag
; next
&& next
< last
; )
792 str
= next_field (next
, '|', &next
, last
);
794 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
798 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
803 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
807 fprintf (table
, " { ");
809 for (i
= 0; i
< size
- 1; i
++)
811 if (((i
+ 1) % 20) != 0)
812 fprintf (table
, "%d, ", modifier
[i
].value
);
814 fprintf (table
, "%d,", modifier
[i
].value
);
815 if (((i
+ 1) % 20) == 0)
816 fprintf (table
, "\n ");
819 fprintf (table
, "%d },\n", modifier
[i
].value
);
823 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
825 char *str
, *next
, *last
;
826 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
828 /* Copy the default opcode modifier. */
829 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
831 if (strcmp (mod
, "0"))
833 last
= mod
+ strlen (mod
);
834 for (next
= mod
; next
&& next
< last
; )
836 str
= next_field (next
, '|', &next
, last
);
838 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
842 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
846 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
847 int macro
, const char *indent
)
851 fprintf (table
, "{ { ");
853 for (i
= 0; i
< size
- 1; i
++)
855 if (((i
+ 1) % 20) != 0)
856 fprintf (table
, "%d, ", types
[i
].value
);
858 fprintf (table
, "%d,", types
[i
].value
);
859 if (((i
+ 1) % 20) == 0)
861 /* We need \\ for macro. */
863 fprintf (table
, " \\\n%s", indent
);
865 fprintf (table
, "\n%s", indent
);
869 fprintf (table
, "%d } }", types
[i
].value
);
873 process_i386_operand_type (FILE *table
, char *op
, int macro
,
874 const char *indent
, int lineno
)
876 char *str
, *next
, *last
;
877 bitfield types
[ARRAY_SIZE (operand_types
)];
879 /* Copy the default operand type. */
880 memcpy (types
, operand_types
, sizeof (types
));
882 if (strcmp (op
, "0"))
884 last
= op
+ strlen (op
);
885 for (next
= op
; next
&& next
< last
; )
887 str
= next_field (next
, '|', &next
, last
);
889 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
892 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
897 output_i386_opcode (FILE *table
, const char *name
, char *str
,
898 char *last
, int lineno
)
901 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
902 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
904 /* Find number of operands. */
905 operands
= next_field (str
, ',', &str
, last
);
907 /* Find base_opcode. */
908 base_opcode
= next_field (str
, ',', &str
, last
);
910 /* Find extension_opcode. */
911 extension_opcode
= next_field (str
, ',', &str
, last
);
913 /* Find opcode_length. */
914 opcode_length
= next_field (str
, ',', &str
, last
);
916 /* Find cpu_flags. */
917 cpu_flags
= next_field (str
, ',', &str
, last
);
919 /* Find opcode_modifier. */
920 opcode_modifier
= next_field (str
, ',', &str
, last
);
922 /* Remove the first {. */
923 str
= remove_leading_whitespaces (str
);
926 str
= remove_leading_whitespaces (str
+ 1);
930 /* There are at least "X}". */
934 /* Remove trailing white spaces and }. */
938 if (ISSPACE (str
[i
]) || str
[i
] == '}')
947 /* Find operand_types. */
948 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
952 operand_types
[i
] = NULL
;
956 operand_types
[i
] = next_field (str
, ',', &str
, last
);
957 if (*operand_types
[i
] == '0')
960 operand_types
[i
] = NULL
;
965 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
966 name
, operands
, base_opcode
, extension_opcode
,
969 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
971 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
973 fprintf (table
, " { ");
975 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
977 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
980 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
985 fprintf (table
, ",\n ");
987 process_i386_operand_type (table
, operand_types
[i
], 0,
990 fprintf (table
, " } },\n");
993 struct opcode_hash_entry
995 struct opcode_hash_entry
*next
;
1001 /* Calculate the hash value of an opcode hash entry P. */
1004 opcode_hash_hash (const void *p
)
1006 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1007 return htab_hash_string (entry
->name
);
1010 /* Compare a string Q against an opcode hash entry P. */
1013 opcode_hash_eq (const void *p
, const void *q
)
1015 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1016 const char *name
= (const char *) q
;
1017 return strcmp (name
, entry
->name
) == 0;
1021 process_i386_opcodes (FILE *table
)
1026 char *str
, *p
, *last
, *name
;
1027 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1028 htab_t opcode_hash_table
;
1029 struct opcode_hash_entry
**opcode_array
;
1030 unsigned int opcode_array_size
= 1024;
1033 filename
= "i386-opc.tbl";
1034 fp
= fopen (filename
, "r");
1037 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1041 opcode_array
= (struct opcode_hash_entry
**)
1042 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1044 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1045 opcode_hash_eq
, NULL
,
1048 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1049 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1051 /* Put everything on opcode array. */
1054 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1059 p
= remove_leading_whitespaces (buf
);
1061 /* Skip comments. */
1062 str
= strstr (p
, "//");
1066 /* Remove trailing white spaces. */
1067 remove_trailing_whitespaces (p
);
1072 /* Ignore comments. */
1080 last
= p
+ strlen (p
);
1083 name
= next_field (p
, ',', &str
, last
);
1085 /* Get the slot in hash table. */
1086 hash_slot
= (struct opcode_hash_entry
**)
1087 htab_find_slot_with_hash (opcode_hash_table
, name
,
1088 htab_hash_string (name
),
1091 if (*hash_slot
== NULL
)
1093 /* It is the new one. Put it on opcode array. */
1094 if (i
>= opcode_array_size
)
1096 /* Grow the opcode array when needed. */
1097 opcode_array_size
+= 1024;
1098 opcode_array
= (struct opcode_hash_entry
**)
1099 xrealloc (opcode_array
,
1100 sizeof (*opcode_array
) * opcode_array_size
);
1103 opcode_array
[i
] = (struct opcode_hash_entry
*)
1104 xmalloc (sizeof (struct opcode_hash_entry
));
1105 opcode_array
[i
]->next
= NULL
;
1106 opcode_array
[i
]->name
= xstrdup (name
);
1107 opcode_array
[i
]->opcode
= xstrdup (str
);
1108 opcode_array
[i
]->lineno
= lineno
;
1109 *hash_slot
= opcode_array
[i
];
1114 /* Append it to the existing one. */
1116 while ((*entry
) != NULL
)
1117 entry
= &(*entry
)->next
;
1118 *entry
= (struct opcode_hash_entry
*)
1119 xmalloc (sizeof (struct opcode_hash_entry
));
1120 (*entry
)->next
= NULL
;
1121 (*entry
)->name
= (*hash_slot
)->name
;
1122 (*entry
)->opcode
= xstrdup (str
);
1123 (*entry
)->lineno
= lineno
;
1127 /* Process opcode array. */
1128 for (j
= 0; j
< i
; j
++)
1130 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1134 lineno
= next
->lineno
;
1135 last
= str
+ strlen (str
);
1136 output_i386_opcode (table
, name
, str
, last
, lineno
);
1142 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1144 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1146 process_i386_opcode_modifier (table
, "0", -1);
1148 fprintf (table
, " { ");
1149 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1150 fprintf (table
, " } }\n");
1152 fprintf (table
, "};\n");
1156 process_i386_registers (FILE *table
)
1160 char *str
, *p
, *last
;
1161 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1162 char *dw2_32_num
, *dw2_64_num
;
1165 filename
= "i386-reg.tbl";
1166 fp
= fopen (filename
, "r");
1168 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1171 fprintf (table
, "\n/* i386 register table. */\n\n");
1172 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
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 fprintf (table
, "%s\n", p
);
1202 last
= p
+ strlen (p
);
1204 /* Find reg_name. */
1205 reg_name
= next_field (p
, ',', &str
, last
);
1207 /* Find reg_type. */
1208 reg_type
= next_field (str
, ',', &str
, last
);
1210 /* Find reg_flags. */
1211 reg_flags
= next_field (str
, ',', &str
, last
);
1214 reg_num
= next_field (str
, ',', &str
, last
);
1216 fprintf (table
, " { \"%s\",\n ", reg_name
);
1218 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1220 /* Find 32-bit Dwarf2 register number. */
1221 dw2_32_num
= next_field (str
, ',', &str
, last
);
1223 /* Find 64-bit Dwarf2 register number. */
1224 dw2_64_num
= next_field (str
, ',', &str
, last
);
1226 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1227 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1232 fprintf (table
, "};\n");
1234 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1238 process_i386_initializers (void)
1241 FILE *fp
= fopen ("i386-init.h", "w");
1245 fail (_("can't create i386-init.h, errno = %s\n"),
1248 process_copyright (fp
);
1250 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1252 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1253 init
= xstrdup (cpu_flag_init
[i
].init
);
1254 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1258 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1260 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1261 init
= xstrdup (operand_type_init
[i
].init
);
1262 process_i386_operand_type (fp
, init
, 1, " ", -1);
1270 /* Program options. */
1271 #define OPTION_SRCDIR 200
1273 struct option long_options
[] =
1275 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1276 {"debug", no_argument
, NULL
, 'd'},
1277 {"version", no_argument
, NULL
, 'V'},
1278 {"help", no_argument
, NULL
, 'h'},
1279 {0, no_argument
, NULL
, 0}
1283 print_version (void)
1285 printf ("%s: version 1.0\n", program_name
);
1290 usage (FILE * stream
, int status
)
1292 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1298 main (int argc
, char **argv
)
1300 extern int chdir (char *);
1301 char *srcdir
= NULL
;
1305 program_name
= *argv
;
1306 xmalloc_set_program_name (program_name
);
1308 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1333 if (chdir (srcdir
) != 0)
1334 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1335 srcdir
, xstrerror (errno
));
1337 /* Check the unused bitfield in i386_cpu_flags. */
1339 c
= CpuNumOfBits
- CpuMax
- 1;
1341 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1344 /* Check the unused bitfield in i386_operand_type. */
1346 c
= OTNumOfBits
- OTMax
- 1;
1348 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1351 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1354 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1355 sizeof (opcode_modifiers
[0]), compare
);
1357 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1358 sizeof (operand_types
[0]), compare
);
1360 table
= fopen ("i386-tbl.h", "w");
1362 fail (_("can't create i386-tbl.h, errno = %s\n"),
1365 process_copyright (table
);
1367 process_i386_opcodes (table
);
1368 process_i386_registers (table
);
1369 process_i386_initializers ();