1 /* Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013
2 Free Software Foundation, Inc.
4 This file is part of the GNU opcodes library.
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
25 #include "libiberty.h"
27 #include "safe-ctype.h"
32 #define _(String) gettext (String)
34 static const char *program_name
= NULL
;
37 typedef struct initializer
43 static initializer cpu_flag_init
[] =
45 { "CPU_UNKNOWN_FLAGS",
46 "~(CpuL1OM|CpuK1OM)" },
47 { "CPU_GENERIC32_FLAGS",
48 "Cpu186|Cpu286|Cpu386" },
49 { "CPU_GENERIC64_FLAGS",
50 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuLM" },
58 "Cpu186|Cpu286|Cpu386" },
60 "Cpu186|Cpu286|Cpu386|Cpu486" },
62 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu387" },
64 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687" },
65 { "CPU_PENTIUMPRO_FLAGS",
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop" },
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX" },
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE" },
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2" },
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM|CpuCX16" },
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuCX16" },
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM|CpuCX16" },
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuRdtscp|CpuLM|CpuCX16" },
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX" },
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX|Cpu3dnow" },
86 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA" },
88 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
89 { "CPU_AMDFAM10_FLAGS",
90 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
92 "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" },
94 "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" },
96 "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" },
98 "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" },
100 "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" },
101 { "CPU_BTVER2_FLAGS",
102 "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" },
110 "Cpu8087|Cpu287|Cpu387|Cpu687|CpuFISTTP" },
111 { "CPU_CLFLUSH_FLAGS",
115 { "CPU_SYSCALL_FLAGS",
122 "CpuMMX|CpuSSE|CpuSSE2" },
124 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
126 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
127 { "CPU_SSE4_1_FLAGS",
128 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
129 { "CPU_SSE4_2_FLAGS",
130 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
131 { "CPU_ANY_SSE_FLAGS",
132 "CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF" },
139 { "CPU_XSAVEOPT_FLAGS",
142 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
143 { "CPU_PCLMUL_FLAGS",
144 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
146 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
148 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA4" },
150 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP" },
161 { "CPU_RDTSCP_FLAGS",
165 { "CPU_FSGSBASE_FLAGS",
179 { "CPU_INVPCID_FLAGS",
181 { "CPU_VMFUNC_FLAGS",
185 { "CPU_3DNOWA_FLAGS",
186 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
187 { "CPU_PADLOCK_FLAGS",
192 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
196 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
198 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2" },
199 { "CPU_AVX512F_FLAGS",
200 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F" },
201 { "CPU_AVX512CD_FLAGS",
202 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512CD" },
203 { "CPU_AVX512ER_FLAGS",
204 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512ER" },
205 { "CPU_AVX512PF_FLAGS",
206 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512PF" },
207 { "CPU_ANY_AVX_FLAGS",
208 "CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF" },
215 { "CPU_RDSEED_FLAGS",
217 { "CPU_PRFCHW_FLAGS",
227 static initializer operand_type_init
[] =
229 { "OPERAND_TYPE_NONE",
231 { "OPERAND_TYPE_REG8",
233 { "OPERAND_TYPE_REG16",
235 { "OPERAND_TYPE_REG32",
237 { "OPERAND_TYPE_REG64",
239 { "OPERAND_TYPE_IMM1",
241 { "OPERAND_TYPE_IMM8",
243 { "OPERAND_TYPE_IMM8S",
245 { "OPERAND_TYPE_IMM16",
247 { "OPERAND_TYPE_IMM32",
249 { "OPERAND_TYPE_IMM32S",
251 { "OPERAND_TYPE_IMM64",
253 { "OPERAND_TYPE_BASEINDEX",
255 { "OPERAND_TYPE_DISP8",
257 { "OPERAND_TYPE_DISP16",
259 { "OPERAND_TYPE_DISP32",
261 { "OPERAND_TYPE_DISP32S",
263 { "OPERAND_TYPE_DISP64",
265 { "OPERAND_TYPE_INOUTPORTREG",
267 { "OPERAND_TYPE_SHIFTCOUNT",
269 { "OPERAND_TYPE_CONTROL",
271 { "OPERAND_TYPE_TEST",
273 { "OPERAND_TYPE_DEBUG",
275 { "OPERAND_TYPE_FLOATREG",
277 { "OPERAND_TYPE_FLOATACC",
279 { "OPERAND_TYPE_SREG2",
281 { "OPERAND_TYPE_SREG3",
283 { "OPERAND_TYPE_ACC",
285 { "OPERAND_TYPE_JUMPABSOLUTE",
287 { "OPERAND_TYPE_REGMMX",
289 { "OPERAND_TYPE_REGXMM",
291 { "OPERAND_TYPE_REGYMM",
293 { "OPERAND_TYPE_REGZMM",
295 { "OPERAND_TYPE_REGMASK",
297 { "OPERAND_TYPE_ESSEG",
299 { "OPERAND_TYPE_ACC32",
301 { "OPERAND_TYPE_ACC64",
303 { "OPERAND_TYPE_INOUTPORTREG",
305 { "OPERAND_TYPE_REG16_INOUTPORTREG",
306 "Reg16|InOutPortReg" },
307 { "OPERAND_TYPE_DISP16_32",
309 { "OPERAND_TYPE_ANYDISP",
310 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
311 { "OPERAND_TYPE_IMM16_32",
313 { "OPERAND_TYPE_IMM16_32S",
315 { "OPERAND_TYPE_IMM16_32_32S",
316 "Imm16|Imm32|Imm32S" },
317 { "OPERAND_TYPE_IMM32_64",
319 { "OPERAND_TYPE_IMM32_32S_DISP32",
320 "Imm32|Imm32S|Disp32" },
321 { "OPERAND_TYPE_IMM64_DISP64",
323 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
324 "Imm32|Imm32S|Imm64|Disp32" },
325 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
326 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
327 { "OPERAND_TYPE_VEC_IMM4",
329 { "OPERAND_TYPE_REGBND",
331 { "OPERAND_TYPE_VEC_DISP8",
335 typedef struct bitfield
342 #define BITFIELD(n) { n, 0, #n }
344 static bitfield cpu_flags
[] =
352 BITFIELD (CpuClflush
),
354 BITFIELD (CpuSYSCALL
),
359 BITFIELD (CpuFISTTP
),
365 BITFIELD (CpuSSE4_1
),
366 BITFIELD (CpuSSE4_2
),
369 BITFIELD (CpuAVX512F
),
370 BITFIELD (CpuAVX512CD
),
371 BITFIELD (CpuAVX512ER
),
372 BITFIELD (CpuAVX512PF
),
377 BITFIELD (Cpu3dnowA
),
378 BITFIELD (CpuPadLock
),
384 BITFIELD (CpuXsaveopt
),
386 BITFIELD (CpuPCLMUL
),
397 BITFIELD (CpuRdtscp
),
398 BITFIELD (CpuFSGSBase
),
405 BITFIELD (CpuINVPCID
),
406 BITFIELD (CpuVMFUNC
),
407 BITFIELD (CpuRDSEED
),
409 BITFIELD (CpuPRFCHW
),
417 BITFIELD (CpuUnused
),
421 static bitfield opcode_modifiers
[] =
427 BITFIELD (ShortForm
),
429 BITFIELD (JumpDword
),
431 BITFIELD (JumpInterSegment
),
438 BITFIELD (CheckRegSize
),
439 BITFIELD (IgnoreSize
),
440 BITFIELD (DefaultSize
),
449 BITFIELD (BNDPrefixOk
),
450 BITFIELD (IsLockable
),
451 BITFIELD (RegKludge
),
452 BITFIELD (FirstXmm0
),
453 BITFIELD (Implicit1stXmm0
),
454 BITFIELD (RepPrefixOk
),
455 BITFIELD (HLEPrefixOk
),
458 BITFIELD (AddrPrefixOp0
),
467 BITFIELD (VexOpcode
),
468 BITFIELD (VexSources
),
469 BITFIELD (VexImmExt
),
476 BITFIELD (Broadcast
),
477 BITFIELD (StaticRounding
),
479 BITFIELD (Disp8MemShift
),
480 BITFIELD (NoDefMask
),
482 BITFIELD (ATTMnemonic
),
483 BITFIELD (ATTSyntax
),
484 BITFIELD (IntelSyntax
),
487 static bitfield operand_types
[] =
506 BITFIELD (BaseIndex
),
512 BITFIELD (InOutPortReg
),
513 BITFIELD (ShiftCount
),
521 BITFIELD (JumpAbsolute
),
534 BITFIELD (Unspecified
),
538 BITFIELD (Vec_Disp8
),
544 static const char *filename
;
547 compare (const void *x
, const void *y
)
549 const bitfield
*xp
= (const bitfield
*) x
;
550 const bitfield
*yp
= (const bitfield
*) y
;
551 return xp
->position
- yp
->position
;
555 fail (const char *message
, ...)
559 va_start (args
, message
);
560 fprintf (stderr
, _("%s: Error: "), program_name
);
561 vfprintf (stderr
, message
, args
);
567 process_copyright (FILE *fp
)
569 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
570 /* Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013\n\
571 Free Software Foundation, Inc.\n\
573 This file is part of the GNU opcodes library.\n\
575 This library is free software; you can redistribute it and/or modify\n\
576 it under the terms of the GNU General Public License as published by\n\
577 the Free Software Foundation; either version 3, or (at your option)\n\
578 any later version.\n\
580 It is distributed in the hope that it will be useful, but WITHOUT\n\
581 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
582 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
583 License for more details.\n\
585 You should have received a copy of the GNU General Public License\n\
586 along with this program; if not, write to the Free Software\n\
587 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
588 MA 02110-1301, USA. */\n");
591 /* Remove leading white spaces. */
594 remove_leading_whitespaces (char *str
)
596 while (ISSPACE (*str
))
601 /* Remove trailing white spaces. */
604 remove_trailing_whitespaces (char *str
)
606 size_t last
= strlen (str
);
614 if (ISSPACE (str
[last
]))
622 /* Find next field separated by SEP and terminate it. Return a
623 pointer to the one after it. */
626 next_field (char *str
, char sep
, char **next
, char *last
)
630 p
= remove_leading_whitespaces (str
);
631 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
634 remove_trailing_whitespaces (p
);
645 set_bitfield (const char *f
, bitfield
*array
, int value
,
646 unsigned int size
, int lineno
)
650 if (strcmp (f
, "CpuFP") == 0)
652 set_bitfield("Cpu387", array
, value
, size
, lineno
);
653 set_bitfield("Cpu287", array
, value
, size
, lineno
);
656 else if (strcmp (f
, "Mmword") == 0)
658 else if (strcmp (f
, "Oword") == 0)
661 for (i
= 0; i
< size
; i
++)
662 if (strcasecmp (array
[i
].name
, f
) == 0)
664 array
[i
].value
= value
;
670 const char *v
= strchr (f
, '=');
677 for (i
= 0; i
< size
; i
++)
678 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
680 value
= strtol (v
+ 1, &end
, 0);
683 array
[i
].value
= value
;
692 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
694 fail (_("Unknown bitfield: %s\n"), f
);
698 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
699 int macro
, const char *comma
, const char *indent
)
703 fprintf (table
, "%s{ { ", indent
);
705 for (i
= 0; i
< size
- 1; i
++)
707 fprintf (table
, "%d, ", flags
[i
].value
);
708 if (((i
+ 1) % 20) == 0)
710 /* We need \\ for macro. */
712 fprintf (table
, " \\\n %s", indent
);
714 fprintf (table
, "\n %s", indent
);
718 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
722 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
723 const char *comma
, const char *indent
,
726 char *str
, *next
, *last
;
728 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
730 /* Copy the default cpu flags. */
731 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
733 if (strcasecmp (flag
, "unknown") == 0)
735 /* We turn on everything except for cpu64 in case of
736 CPU_UNKNOWN_FLAGS. */
737 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
738 if (flags
[i
].position
!= Cpu64
)
741 else if (flag
[0] == '~')
743 last
= flag
+ strlen (flag
);
750 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
757 /* First we turn on everything except for cpu64. */
758 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
759 if (flags
[i
].position
!= Cpu64
)
762 /* Turn off selective bits. */
763 for (; next
&& next
< last
; )
765 str
= next_field (next
, '|', &next
, last
);
767 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
770 else if (strcmp (flag
, "0"))
772 /* Turn on selective bits. */
773 last
= flag
+ strlen (flag
);
774 for (next
= flag
; next
&& next
< last
; )
776 str
= next_field (next
, '|', &next
, last
);
778 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
782 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
787 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
791 fprintf (table
, " { ");
793 for (i
= 0; i
< size
- 1; i
++)
795 fprintf (table
, "%d, ", modifier
[i
].value
);
796 if (((i
+ 1) % 20) == 0)
797 fprintf (table
, "\n ");
800 fprintf (table
, "%d },\n", modifier
[i
].value
);
804 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
806 char *str
, *next
, *last
;
807 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
809 /* Copy the default opcode modifier. */
810 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
812 if (strcmp (mod
, "0"))
814 last
= mod
+ strlen (mod
);
815 for (next
= mod
; next
&& next
< last
; )
817 str
= next_field (next
, '|', &next
, last
);
819 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
823 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
827 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
828 int macro
, const char *indent
)
832 fprintf (table
, "{ { ");
834 for (i
= 0; i
< size
- 1; i
++)
836 fprintf (table
, "%d, ", types
[i
].value
);
837 if (((i
+ 1) % 20) == 0)
839 /* We need \\ for macro. */
841 fprintf (table
, "\\\n%s", indent
);
843 fprintf (table
, "\n%s", indent
);
847 fprintf (table
, "%d } }", types
[i
].value
);
851 process_i386_operand_type (FILE *table
, char *op
, int macro
,
852 const char *indent
, int lineno
)
854 char *str
, *next
, *last
;
855 bitfield types
[ARRAY_SIZE (operand_types
)];
857 /* Copy the default operand type. */
858 memcpy (types
, operand_types
, sizeof (types
));
860 if (strcmp (op
, "0"))
862 last
= op
+ strlen (op
);
863 for (next
= op
; next
&& next
< last
; )
865 str
= next_field (next
, '|', &next
, last
);
867 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
870 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
875 output_i386_opcode (FILE *table
, const char *name
, char *str
,
876 char *last
, int lineno
)
879 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
880 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
882 /* Find number of operands. */
883 operands
= next_field (str
, ',', &str
, last
);
885 /* Find base_opcode. */
886 base_opcode
= next_field (str
, ',', &str
, last
);
888 /* Find extension_opcode. */
889 extension_opcode
= next_field (str
, ',', &str
, last
);
891 /* Find opcode_length. */
892 opcode_length
= next_field (str
, ',', &str
, last
);
894 /* Find cpu_flags. */
895 cpu_flags
= next_field (str
, ',', &str
, last
);
897 /* Find opcode_modifier. */
898 opcode_modifier
= next_field (str
, ',', &str
, last
);
900 /* Remove the first {. */
901 str
= remove_leading_whitespaces (str
);
904 str
= remove_leading_whitespaces (str
+ 1);
908 /* There are at least "X}". */
912 /* Remove trailing white spaces and }. */
916 if (ISSPACE (str
[i
]) || str
[i
] == '}')
925 /* Find operand_types. */
926 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
930 operand_types
[i
] = NULL
;
934 operand_types
[i
] = next_field (str
, ',', &str
, last
);
935 if (*operand_types
[i
] == '0')
938 operand_types
[i
] = NULL
;
943 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
944 name
, operands
, base_opcode
, extension_opcode
,
947 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
949 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
951 fprintf (table
, " { ");
953 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
955 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
958 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
963 fprintf (table
, ",\n ");
965 process_i386_operand_type (table
, operand_types
[i
], 0,
968 fprintf (table
, " } },\n");
971 struct opcode_hash_entry
973 struct opcode_hash_entry
*next
;
979 /* Calculate the hash value of an opcode hash entry P. */
982 opcode_hash_hash (const void *p
)
984 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
985 return htab_hash_string (entry
->name
);
988 /* Compare a string Q against an opcode hash entry P. */
991 opcode_hash_eq (const void *p
, const void *q
)
993 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
994 const char *name
= (const char *) q
;
995 return strcmp (name
, entry
->name
) == 0;
999 process_i386_opcodes (FILE *table
)
1004 char *str
, *p
, *last
, *name
;
1005 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1006 htab_t opcode_hash_table
;
1007 struct opcode_hash_entry
**opcode_array
;
1008 unsigned int opcode_array_size
= 1024;
1011 filename
= "i386-opc.tbl";
1012 fp
= fopen (filename
, "r");
1015 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1019 opcode_array
= (struct opcode_hash_entry
**)
1020 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1022 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1023 opcode_hash_eq
, NULL
,
1026 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1027 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1029 /* Put everything on opcode array. */
1032 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1037 p
= remove_leading_whitespaces (buf
);
1039 /* Skip comments. */
1040 str
= strstr (p
, "//");
1044 /* Remove trailing white spaces. */
1045 remove_trailing_whitespaces (p
);
1050 /* Ignore comments. */
1058 last
= p
+ strlen (p
);
1061 name
= next_field (p
, ',', &str
, last
);
1063 /* Get the slot in hash table. */
1064 hash_slot
= (struct opcode_hash_entry
**)
1065 htab_find_slot_with_hash (opcode_hash_table
, name
,
1066 htab_hash_string (name
),
1069 if (*hash_slot
== NULL
)
1071 /* It is the new one. Put it on opcode array. */
1072 if (i
>= opcode_array_size
)
1074 /* Grow the opcode array when needed. */
1075 opcode_array_size
+= 1024;
1076 opcode_array
= (struct opcode_hash_entry
**)
1077 xrealloc (opcode_array
,
1078 sizeof (*opcode_array
) * opcode_array_size
);
1081 opcode_array
[i
] = (struct opcode_hash_entry
*)
1082 xmalloc (sizeof (struct opcode_hash_entry
));
1083 opcode_array
[i
]->next
= NULL
;
1084 opcode_array
[i
]->name
= xstrdup (name
);
1085 opcode_array
[i
]->opcode
= xstrdup (str
);
1086 opcode_array
[i
]->lineno
= lineno
;
1087 *hash_slot
= opcode_array
[i
];
1092 /* Append it to the existing one. */
1094 while ((*entry
) != NULL
)
1095 entry
= &(*entry
)->next
;
1096 *entry
= (struct opcode_hash_entry
*)
1097 xmalloc (sizeof (struct opcode_hash_entry
));
1098 (*entry
)->next
= NULL
;
1099 (*entry
)->name
= (*hash_slot
)->name
;
1100 (*entry
)->opcode
= xstrdup (str
);
1101 (*entry
)->lineno
= lineno
;
1105 /* Process opcode array. */
1106 for (j
= 0; j
< i
; j
++)
1108 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1112 lineno
= next
->lineno
;
1113 last
= str
+ strlen (str
);
1114 output_i386_opcode (table
, name
, str
, last
, lineno
);
1120 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1122 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1124 process_i386_opcode_modifier (table
, "0", -1);
1126 fprintf (table
, " { ");
1127 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1128 fprintf (table
, " } }\n");
1130 fprintf (table
, "};\n");
1134 process_i386_registers (FILE *table
)
1138 char *str
, *p
, *last
;
1139 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1140 char *dw2_32_num
, *dw2_64_num
;
1143 filename
= "i386-reg.tbl";
1144 fp
= fopen (filename
, "r");
1146 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1149 fprintf (table
, "\n/* i386 register table. */\n\n");
1150 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1154 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1159 p
= remove_leading_whitespaces (buf
);
1161 /* Skip comments. */
1162 str
= strstr (p
, "//");
1166 /* Remove trailing white spaces. */
1167 remove_trailing_whitespaces (p
);
1172 fprintf (table
, "%s\n", p
);
1180 last
= p
+ strlen (p
);
1182 /* Find reg_name. */
1183 reg_name
= next_field (p
, ',', &str
, last
);
1185 /* Find reg_type. */
1186 reg_type
= next_field (str
, ',', &str
, last
);
1188 /* Find reg_flags. */
1189 reg_flags
= next_field (str
, ',', &str
, last
);
1192 reg_num
= next_field (str
, ',', &str
, last
);
1194 fprintf (table
, " { \"%s\",\n ", reg_name
);
1196 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1198 /* Find 32-bit Dwarf2 register number. */
1199 dw2_32_num
= next_field (str
, ',', &str
, last
);
1201 /* Find 64-bit Dwarf2 register number. */
1202 dw2_64_num
= next_field (str
, ',', &str
, last
);
1204 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1205 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1210 fprintf (table
, "};\n");
1212 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1216 process_i386_initializers (void)
1219 FILE *fp
= fopen ("i386-init.h", "w");
1223 fail (_("can't create i386-init.h, errno = %s\n"),
1226 process_copyright (fp
);
1228 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1230 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1231 init
= xstrdup (cpu_flag_init
[i
].init
);
1232 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1236 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1238 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1239 init
= xstrdup (operand_type_init
[i
].init
);
1240 process_i386_operand_type (fp
, init
, 1, " ", -1);
1248 /* Program options. */
1249 #define OPTION_SRCDIR 200
1251 struct option long_options
[] =
1253 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1254 {"debug", no_argument
, NULL
, 'd'},
1255 {"version", no_argument
, NULL
, 'V'},
1256 {"help", no_argument
, NULL
, 'h'},
1257 {0, no_argument
, NULL
, 0}
1261 print_version (void)
1263 printf ("%s: version 1.0\n", program_name
);
1268 usage (FILE * stream
, int status
)
1270 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1276 main (int argc
, char **argv
)
1278 extern int chdir (char *);
1279 char *srcdir
= NULL
;
1283 program_name
= *argv
;
1284 xmalloc_set_program_name (program_name
);
1286 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1311 if (chdir (srcdir
) != 0)
1312 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1313 srcdir
, xstrerror (errno
));
1315 /* Check the unused bitfield in i386_cpu_flags. */
1317 c
= CpuNumOfBits
- CpuMax
- 1;
1319 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1322 /* Check the unused bitfield in i386_operand_type. */
1324 c
= OTNumOfBits
- OTMax
- 1;
1326 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1329 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1332 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1333 sizeof (opcode_modifiers
[0]), compare
);
1335 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1336 sizeof (operand_types
[0]), compare
);
1338 table
= fopen ("i386-tbl.h", "w");
1340 fail (_("can't create i386-tbl.h, errno = %s\n"),
1343 process_copyright (table
);
1345 process_i386_opcodes (table
);
1346 process_i386_registers (table
);
1347 process_i386_initializers ();