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_AVX512BW_FLAGS",
235 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512BW" },
236 { "CPU_AVX512VL_FLAGS",
237 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuAVX2|CpuAVX512F|CpuAVX512VL" },
240 static initializer operand_type_init
[] =
242 { "OPERAND_TYPE_NONE",
244 { "OPERAND_TYPE_REG8",
246 { "OPERAND_TYPE_REG16",
248 { "OPERAND_TYPE_REG32",
250 { "OPERAND_TYPE_REG64",
252 { "OPERAND_TYPE_IMM1",
254 { "OPERAND_TYPE_IMM8",
256 { "OPERAND_TYPE_IMM8S",
258 { "OPERAND_TYPE_IMM16",
260 { "OPERAND_TYPE_IMM32",
262 { "OPERAND_TYPE_IMM32S",
264 { "OPERAND_TYPE_IMM64",
266 { "OPERAND_TYPE_BASEINDEX",
268 { "OPERAND_TYPE_DISP8",
270 { "OPERAND_TYPE_DISP16",
272 { "OPERAND_TYPE_DISP32",
274 { "OPERAND_TYPE_DISP32S",
276 { "OPERAND_TYPE_DISP64",
278 { "OPERAND_TYPE_INOUTPORTREG",
280 { "OPERAND_TYPE_SHIFTCOUNT",
282 { "OPERAND_TYPE_CONTROL",
284 { "OPERAND_TYPE_TEST",
286 { "OPERAND_TYPE_DEBUG",
288 { "OPERAND_TYPE_FLOATREG",
290 { "OPERAND_TYPE_FLOATACC",
292 { "OPERAND_TYPE_SREG2",
294 { "OPERAND_TYPE_SREG3",
296 { "OPERAND_TYPE_ACC",
298 { "OPERAND_TYPE_JUMPABSOLUTE",
300 { "OPERAND_TYPE_REGMMX",
302 { "OPERAND_TYPE_REGXMM",
304 { "OPERAND_TYPE_REGYMM",
306 { "OPERAND_TYPE_REGZMM",
308 { "OPERAND_TYPE_REGMASK",
310 { "OPERAND_TYPE_ESSEG",
312 { "OPERAND_TYPE_ACC32",
314 { "OPERAND_TYPE_ACC64",
316 { "OPERAND_TYPE_INOUTPORTREG",
318 { "OPERAND_TYPE_REG16_INOUTPORTREG",
319 "Reg16|InOutPortReg" },
320 { "OPERAND_TYPE_DISP16_32",
322 { "OPERAND_TYPE_ANYDISP",
323 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
324 { "OPERAND_TYPE_IMM16_32",
326 { "OPERAND_TYPE_IMM16_32S",
328 { "OPERAND_TYPE_IMM16_32_32S",
329 "Imm16|Imm32|Imm32S" },
330 { "OPERAND_TYPE_IMM32_64",
332 { "OPERAND_TYPE_IMM32_32S_DISP32",
333 "Imm32|Imm32S|Disp32" },
334 { "OPERAND_TYPE_IMM64_DISP64",
336 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
337 "Imm32|Imm32S|Imm64|Disp32" },
338 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
339 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
340 { "OPERAND_TYPE_VEC_IMM4",
342 { "OPERAND_TYPE_REGBND",
344 { "OPERAND_TYPE_VEC_DISP8",
348 typedef struct bitfield
355 #define BITFIELD(n) { n, 0, #n }
357 static bitfield cpu_flags
[] =
365 BITFIELD (CpuClflush
),
367 BITFIELD (CpuSYSCALL
),
372 BITFIELD (CpuFISTTP
),
378 BITFIELD (CpuSSE4_1
),
379 BITFIELD (CpuSSE4_2
),
382 BITFIELD (CpuAVX512F
),
383 BITFIELD (CpuAVX512CD
),
384 BITFIELD (CpuAVX512ER
),
385 BITFIELD (CpuAVX512PF
),
386 BITFIELD (CpuAVX512VL
),
387 BITFIELD (CpuAVX512BW
),
392 BITFIELD (Cpu3dnowA
),
393 BITFIELD (CpuPadLock
),
399 BITFIELD (CpuXsaveopt
),
401 BITFIELD (CpuPCLMUL
),
412 BITFIELD (CpuRdtscp
),
413 BITFIELD (CpuFSGSBase
),
420 BITFIELD (CpuINVPCID
),
421 BITFIELD (CpuVMFUNC
),
422 BITFIELD (CpuRDSEED
),
424 BITFIELD (CpuPRFCHW
),
428 BITFIELD (CpuClflushOpt
),
429 BITFIELD (CpuXSAVES
),
430 BITFIELD (CpuXSAVEC
),
431 BITFIELD (CpuPREFETCHWT1
),
437 BITFIELD (CpuUnused
),
441 static bitfield opcode_modifiers
[] =
447 BITFIELD (ShortForm
),
449 BITFIELD (JumpDword
),
451 BITFIELD (JumpInterSegment
),
458 BITFIELD (CheckRegSize
),
459 BITFIELD (IgnoreSize
),
460 BITFIELD (DefaultSize
),
469 BITFIELD (BNDPrefixOk
),
470 BITFIELD (IsLockable
),
471 BITFIELD (RegKludge
),
472 BITFIELD (FirstXmm0
),
473 BITFIELD (Implicit1stXmm0
),
474 BITFIELD (RepPrefixOk
),
475 BITFIELD (HLEPrefixOk
),
478 BITFIELD (AddrPrefixOp0
),
487 BITFIELD (VexOpcode
),
488 BITFIELD (VexSources
),
489 BITFIELD (VexImmExt
),
496 BITFIELD (Broadcast
),
497 BITFIELD (StaticRounding
),
499 BITFIELD (Disp8MemShift
),
500 BITFIELD (NoDefMask
),
502 BITFIELD (ATTMnemonic
),
503 BITFIELD (ATTSyntax
),
504 BITFIELD (IntelSyntax
),
507 static bitfield operand_types
[] =
526 BITFIELD (BaseIndex
),
532 BITFIELD (InOutPortReg
),
533 BITFIELD (ShiftCount
),
541 BITFIELD (JumpAbsolute
),
554 BITFIELD (Unspecified
),
558 BITFIELD (Vec_Disp8
),
564 static const char *filename
;
567 compare (const void *x
, const void *y
)
569 const bitfield
*xp
= (const bitfield
*) x
;
570 const bitfield
*yp
= (const bitfield
*) y
;
571 return xp
->position
- yp
->position
;
575 fail (const char *message
, ...)
579 va_start (args
, message
);
580 fprintf (stderr
, _("%s: Error: "), program_name
);
581 vfprintf (stderr
, message
, args
);
587 process_copyright (FILE *fp
)
589 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
590 /* Copyright (C) 2007-2014 Free Software Foundation, Inc.\n\
592 This file is part of the GNU opcodes library.\n\
594 This library is free software; you can redistribute it and/or modify\n\
595 it under the terms of the GNU General Public License as published by\n\
596 the Free Software Foundation; either version 3, or (at your option)\n\
597 any later version.\n\
599 It is distributed in the hope that it will be useful, but WITHOUT\n\
600 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
601 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
602 License for more details.\n\
604 You should have received a copy of the GNU General Public License\n\
605 along with this program; if not, write to the Free Software\n\
606 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
607 MA 02110-1301, USA. */\n");
610 /* Remove leading white spaces. */
613 remove_leading_whitespaces (char *str
)
615 while (ISSPACE (*str
))
620 /* Remove trailing white spaces. */
623 remove_trailing_whitespaces (char *str
)
625 size_t last
= strlen (str
);
633 if (ISSPACE (str
[last
]))
641 /* Find next field separated by SEP and terminate it. Return a
642 pointer to the one after it. */
645 next_field (char *str
, char sep
, char **next
, char *last
)
649 p
= remove_leading_whitespaces (str
);
650 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
653 remove_trailing_whitespaces (p
);
664 set_bitfield (const char *f
, bitfield
*array
, int value
,
665 unsigned int size
, int lineno
)
669 if (strcmp (f
, "CpuFP") == 0)
671 set_bitfield("Cpu387", array
, value
, size
, lineno
);
672 set_bitfield("Cpu287", array
, value
, size
, lineno
);
675 else if (strcmp (f
, "Mmword") == 0)
677 else if (strcmp (f
, "Oword") == 0)
680 for (i
= 0; i
< size
; i
++)
681 if (strcasecmp (array
[i
].name
, f
) == 0)
683 array
[i
].value
= value
;
689 const char *v
= strchr (f
, '=');
696 for (i
= 0; i
< size
; i
++)
697 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
699 value
= strtol (v
+ 1, &end
, 0);
702 array
[i
].value
= value
;
711 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
713 fail (_("Unknown bitfield: %s\n"), f
);
717 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
718 int macro
, const char *comma
, const char *indent
)
722 fprintf (table
, "%s{ { ", indent
);
724 for (i
= 0; i
< size
- 1; i
++)
726 if (((i
+ 1) % 20) != 0)
727 fprintf (table
, "%d, ", flags
[i
].value
);
729 fprintf (table
, "%d,", flags
[i
].value
);
730 if (((i
+ 1) % 20) == 0)
732 /* We need \\ for macro. */
734 fprintf (table
, " \\\n %s", indent
);
736 fprintf (table
, "\n %s", indent
);
740 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
744 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
745 const char *comma
, const char *indent
,
748 char *str
, *next
, *last
;
750 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
752 /* Copy the default cpu flags. */
753 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
755 if (strcasecmp (flag
, "unknown") == 0)
757 /* We turn on everything except for cpu64 in case of
758 CPU_UNKNOWN_FLAGS. */
759 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
760 if (flags
[i
].position
!= Cpu64
)
763 else if (flag
[0] == '~')
765 last
= flag
+ strlen (flag
);
772 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
779 /* First we turn on everything except for cpu64. */
780 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
781 if (flags
[i
].position
!= Cpu64
)
784 /* Turn off selective bits. */
785 for (; next
&& next
< last
; )
787 str
= next_field (next
, '|', &next
, last
);
789 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
792 else if (strcmp (flag
, "0"))
794 /* Turn on selective bits. */
795 last
= flag
+ strlen (flag
);
796 for (next
= flag
; next
&& next
< last
; )
798 str
= next_field (next
, '|', &next
, last
);
800 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
804 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
809 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
813 fprintf (table
, " { ");
815 for (i
= 0; i
< size
- 1; i
++)
817 if (((i
+ 1) % 20) != 0)
818 fprintf (table
, "%d, ", modifier
[i
].value
);
820 fprintf (table
, "%d,", modifier
[i
].value
);
821 if (((i
+ 1) % 20) == 0)
822 fprintf (table
, "\n ");
825 fprintf (table
, "%d },\n", modifier
[i
].value
);
829 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
831 char *str
, *next
, *last
;
832 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
834 /* Copy the default opcode modifier. */
835 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
837 if (strcmp (mod
, "0"))
839 last
= mod
+ strlen (mod
);
840 for (next
= mod
; next
&& next
< last
; )
842 str
= next_field (next
, '|', &next
, last
);
844 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
848 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
852 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
853 int macro
, const char *indent
)
857 fprintf (table
, "{ { ");
859 for (i
= 0; i
< size
- 1; i
++)
861 if (((i
+ 1) % 20) != 0)
862 fprintf (table
, "%d, ", types
[i
].value
);
864 fprintf (table
, "%d,", types
[i
].value
);
865 if (((i
+ 1) % 20) == 0)
867 /* We need \\ for macro. */
869 fprintf (table
, " \\\n%s", indent
);
871 fprintf (table
, "\n%s", indent
);
875 fprintf (table
, "%d } }", types
[i
].value
);
879 process_i386_operand_type (FILE *table
, char *op
, int macro
,
880 const char *indent
, int lineno
)
882 char *str
, *next
, *last
;
883 bitfield types
[ARRAY_SIZE (operand_types
)];
885 /* Copy the default operand type. */
886 memcpy (types
, operand_types
, sizeof (types
));
888 if (strcmp (op
, "0"))
890 last
= op
+ strlen (op
);
891 for (next
= op
; next
&& next
< last
; )
893 str
= next_field (next
, '|', &next
, last
);
895 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
898 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
903 output_i386_opcode (FILE *table
, const char *name
, char *str
,
904 char *last
, int lineno
)
907 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
908 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
910 /* Find number of operands. */
911 operands
= next_field (str
, ',', &str
, last
);
913 /* Find base_opcode. */
914 base_opcode
= next_field (str
, ',', &str
, last
);
916 /* Find extension_opcode. */
917 extension_opcode
= next_field (str
, ',', &str
, last
);
919 /* Find opcode_length. */
920 opcode_length
= next_field (str
, ',', &str
, last
);
922 /* Find cpu_flags. */
923 cpu_flags
= next_field (str
, ',', &str
, last
);
925 /* Find opcode_modifier. */
926 opcode_modifier
= next_field (str
, ',', &str
, last
);
928 /* Remove the first {. */
929 str
= remove_leading_whitespaces (str
);
932 str
= remove_leading_whitespaces (str
+ 1);
936 /* There are at least "X}". */
940 /* Remove trailing white spaces and }. */
944 if (ISSPACE (str
[i
]) || str
[i
] == '}')
953 /* Find operand_types. */
954 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
958 operand_types
[i
] = NULL
;
962 operand_types
[i
] = next_field (str
, ',', &str
, last
);
963 if (*operand_types
[i
] == '0')
966 operand_types
[i
] = NULL
;
971 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
972 name
, operands
, base_opcode
, extension_opcode
,
975 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
977 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
979 fprintf (table
, " { ");
981 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
983 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
986 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
991 fprintf (table
, ",\n ");
993 process_i386_operand_type (table
, operand_types
[i
], 0,
996 fprintf (table
, " } },\n");
999 struct opcode_hash_entry
1001 struct opcode_hash_entry
*next
;
1007 /* Calculate the hash value of an opcode hash entry P. */
1010 opcode_hash_hash (const void *p
)
1012 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1013 return htab_hash_string (entry
->name
);
1016 /* Compare a string Q against an opcode hash entry P. */
1019 opcode_hash_eq (const void *p
, const void *q
)
1021 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1022 const char *name
= (const char *) q
;
1023 return strcmp (name
, entry
->name
) == 0;
1027 process_i386_opcodes (FILE *table
)
1032 char *str
, *p
, *last
, *name
;
1033 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
1034 htab_t opcode_hash_table
;
1035 struct opcode_hash_entry
**opcode_array
;
1036 unsigned int opcode_array_size
= 1024;
1039 filename
= "i386-opc.tbl";
1040 fp
= fopen (filename
, "r");
1043 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
1047 opcode_array
= (struct opcode_hash_entry
**)
1048 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
1050 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1051 opcode_hash_eq
, NULL
,
1054 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1055 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1057 /* Put everything on opcode array. */
1060 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1065 p
= remove_leading_whitespaces (buf
);
1067 /* Skip comments. */
1068 str
= strstr (p
, "//");
1072 /* Remove trailing white spaces. */
1073 remove_trailing_whitespaces (p
);
1078 /* Ignore comments. */
1086 last
= p
+ strlen (p
);
1089 name
= next_field (p
, ',', &str
, last
);
1091 /* Get the slot in hash table. */
1092 hash_slot
= (struct opcode_hash_entry
**)
1093 htab_find_slot_with_hash (opcode_hash_table
, name
,
1094 htab_hash_string (name
),
1097 if (*hash_slot
== NULL
)
1099 /* It is the new one. Put it on opcode array. */
1100 if (i
>= opcode_array_size
)
1102 /* Grow the opcode array when needed. */
1103 opcode_array_size
+= 1024;
1104 opcode_array
= (struct opcode_hash_entry
**)
1105 xrealloc (opcode_array
,
1106 sizeof (*opcode_array
) * opcode_array_size
);
1109 opcode_array
[i
] = (struct opcode_hash_entry
*)
1110 xmalloc (sizeof (struct opcode_hash_entry
));
1111 opcode_array
[i
]->next
= NULL
;
1112 opcode_array
[i
]->name
= xstrdup (name
);
1113 opcode_array
[i
]->opcode
= xstrdup (str
);
1114 opcode_array
[i
]->lineno
= lineno
;
1115 *hash_slot
= opcode_array
[i
];
1120 /* Append it to the existing one. */
1122 while ((*entry
) != NULL
)
1123 entry
= &(*entry
)->next
;
1124 *entry
= (struct opcode_hash_entry
*)
1125 xmalloc (sizeof (struct opcode_hash_entry
));
1126 (*entry
)->next
= NULL
;
1127 (*entry
)->name
= (*hash_slot
)->name
;
1128 (*entry
)->opcode
= xstrdup (str
);
1129 (*entry
)->lineno
= lineno
;
1133 /* Process opcode array. */
1134 for (j
= 0; j
< i
; j
++)
1136 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1140 lineno
= next
->lineno
;
1141 last
= str
+ strlen (str
);
1142 output_i386_opcode (table
, name
, str
, last
, lineno
);
1148 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1150 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1152 process_i386_opcode_modifier (table
, "0", -1);
1154 fprintf (table
, " { ");
1155 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1156 fprintf (table
, " } }\n");
1158 fprintf (table
, "};\n");
1162 process_i386_registers (FILE *table
)
1166 char *str
, *p
, *last
;
1167 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1168 char *dw2_32_num
, *dw2_64_num
;
1171 filename
= "i386-reg.tbl";
1172 fp
= fopen (filename
, "r");
1174 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1177 fprintf (table
, "\n/* i386 register table. */\n\n");
1178 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1182 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1187 p
= remove_leading_whitespaces (buf
);
1189 /* Skip comments. */
1190 str
= strstr (p
, "//");
1194 /* Remove trailing white spaces. */
1195 remove_trailing_whitespaces (p
);
1200 fprintf (table
, "%s\n", p
);
1208 last
= p
+ strlen (p
);
1210 /* Find reg_name. */
1211 reg_name
= next_field (p
, ',', &str
, last
);
1213 /* Find reg_type. */
1214 reg_type
= next_field (str
, ',', &str
, last
);
1216 /* Find reg_flags. */
1217 reg_flags
= next_field (str
, ',', &str
, last
);
1220 reg_num
= next_field (str
, ',', &str
, last
);
1222 fprintf (table
, " { \"%s\",\n ", reg_name
);
1224 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1226 /* Find 32-bit Dwarf2 register number. */
1227 dw2_32_num
= next_field (str
, ',', &str
, last
);
1229 /* Find 64-bit Dwarf2 register number. */
1230 dw2_64_num
= next_field (str
, ',', &str
, last
);
1232 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1233 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1238 fprintf (table
, "};\n");
1240 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1244 process_i386_initializers (void)
1247 FILE *fp
= fopen ("i386-init.h", "w");
1251 fail (_("can't create i386-init.h, errno = %s\n"),
1254 process_copyright (fp
);
1256 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1258 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1259 init
= xstrdup (cpu_flag_init
[i
].init
);
1260 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1264 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1266 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1267 init
= xstrdup (operand_type_init
[i
].init
);
1268 process_i386_operand_type (fp
, init
, 1, " ", -1);
1276 /* Program options. */
1277 #define OPTION_SRCDIR 200
1279 struct option long_options
[] =
1281 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1282 {"debug", no_argument
, NULL
, 'd'},
1283 {"version", no_argument
, NULL
, 'V'},
1284 {"help", no_argument
, NULL
, 'h'},
1285 {0, no_argument
, NULL
, 0}
1289 print_version (void)
1291 printf ("%s: version 1.0\n", program_name
);
1296 usage (FILE * stream
, int status
)
1298 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1304 main (int argc
, char **argv
)
1306 extern int chdir (char *);
1307 char *srcdir
= NULL
;
1311 program_name
= *argv
;
1312 xmalloc_set_program_name (program_name
);
1314 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1339 if (chdir (srcdir
) != 0)
1340 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1341 srcdir
, xstrerror (errno
));
1343 /* Check the unused bitfield in i386_cpu_flags. */
1345 c
= CpuNumOfBits
- CpuMax
- 1;
1347 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1350 /* Check the unused bitfield in i386_operand_type. */
1352 c
= OTNumOfBits
- OTMax
- 1;
1354 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1357 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1360 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1361 sizeof (opcode_modifiers
[0]), compare
);
1363 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1364 sizeof (operand_types
[0]), compare
);
1366 table
= fopen ("i386-tbl.h", "w");
1368 fail (_("can't create i386-tbl.h, errno = %s\n"),
1371 process_copyright (table
);
1373 process_i386_opcodes (table
);
1374 process_i386_registers (table
);
1375 process_i386_initializers ();