1/* Copyright (C) 2007-2022 Free Software Foundation, Inc.
2
3   This file is part of the GNU opcodes library.
4
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)
8   any later version.
9
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.
14
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.  */
19
20#include "sysdep.h"
21#include <stdio.h>
22#include <errno.h>
23#include "getopt.h"
24#include "libiberty.h"
25#include "hashtab.h"
26#include "safe-ctype.h"
27
28#include "i386-opc.h"
29
30#include <libintl.h>
31#define _(String) gettext (String)
32
33/* Build-time checks are preferrable over runtime ones.  Use this construct
34   in preference where possible.  */
35#define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
36
37static const char *program_name = NULL;
38static int debug = 0;
39
40typedef struct initializer
41{
42  const char *name;
43  const char *init;
44} initializer;
45
46static initializer cpu_flag_init[] =
47{
48  { "CPU_UNKNOWN_FLAGS",
49    "~CpuIAMCU" },
50  { "CPU_GENERIC32_FLAGS",
51    "Cpu186|Cpu286|Cpu386" },
52  { "CPU_GENERIC64_FLAGS",
53    "CPU_PENTIUMPRO_FLAGS|CpuClflush|CpuSYSCALL|CPU_MMX_FLAGS|CPU_SSE2_FLAGS|CpuLM" },
54  { "CPU_NONE_FLAGS",
55   "0" },
56  { "CPU_I186_FLAGS",
57    "Cpu186" },
58  { "CPU_I286_FLAGS",
59    "CPU_I186_FLAGS|Cpu286" },
60  { "CPU_I386_FLAGS",
61    "CPU_I286_FLAGS|Cpu386" },
62  { "CPU_I486_FLAGS",
63    "CPU_I386_FLAGS|Cpu486" },
64  { "CPU_I586_FLAGS",
65    "CPU_I486_FLAGS|Cpu387|Cpu586" },
66  { "CPU_I686_FLAGS",
67    "CPU_I586_FLAGS|Cpu686|Cpu687|CpuCMOV|CpuFXSR" },
68  { "CPU_PENTIUMPRO_FLAGS",
69    "CPU_I686_FLAGS|CpuNop" },
70  { "CPU_P2_FLAGS",
71    "CPU_PENTIUMPRO_FLAGS|CPU_MMX_FLAGS" },
72  { "CPU_P3_FLAGS",
73    "CPU_P2_FLAGS|CPU_SSE_FLAGS" },
74  { "CPU_P4_FLAGS",
75    "CPU_P3_FLAGS|CpuClflush|CPU_SSE2_FLAGS" },
76  { "CPU_NOCONA_FLAGS",
77    "CPU_GENERIC64_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
78  { "CPU_CORE_FLAGS",
79    "CPU_P4_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
80  { "CPU_CORE2_FLAGS",
81    "CPU_NOCONA_FLAGS|CPU_SSSE3_FLAGS" },
82  { "CPU_COREI7_FLAGS",
83    "CPU_CORE2_FLAGS|CPU_SSE4_2_FLAGS|CpuRdtscp" },
84  { "CPU_K6_FLAGS",
85    "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CPU_MMX_FLAGS" },
86  { "CPU_K6_2_FLAGS",
87    "CPU_K6_FLAGS|Cpu3dnow" },
88  { "CPU_ATHLON_FLAGS",
89    "CPU_K6_2_FLAGS|Cpu686|Cpu687|CpuNop|Cpu3dnowA" },
90  { "CPU_K8_FLAGS",
91    "CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
92  { "CPU_AMDFAM10_FLAGS",
93    "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuLZCNT|CpuPOPCNT" },
94  { "CPU_BDVER1_FLAGS",
95    "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuLZCNT|CpuPOPCNT|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW" },
96  { "CPU_BDVER2_FLAGS",
97    "CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
98  { "CPU_BDVER3_FLAGS",
99    "CPU_BDVER2_FLAGS|CpuXsaveopt|CpuFSGSBase" },
100  { "CPU_BDVER4_FLAGS",
101    "CPU_BDVER3_FLAGS|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuMWAITX" },
102  { "CPU_ZNVER1_FLAGS",
103    "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_AVX2_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW|CpuFMA|CpuBMI|CpuF16C|CpuXsaveopt|CpuFSGSBase|CpuMovbe|CpuBMI2|CpuRdRnd|CpuADX|CpuRdSeed|CpuSMAP|CpuSHA|CpuXSAVEC|CpuXSAVES|CpuClflushOpt|CpuCLZERO|CpuMWAITX" },
104  { "CPU_ZNVER2_FLAGS",
105    "CPU_ZNVER1_FLAGS|CpuCLWB|CpuRDPID|CpuRDPRU|CpuMCOMMIT|CpuWBNOINVD" },
106  { "CPU_ZNVER3_FLAGS",
107    "CPU_ZNVER2_FLAGS|CpuINVLPGB|CpuTLBSYNC|CpuVAES|CpuVPCLMULQDQ|CpuINVPCID|CpuSNP|CpuOSPKE" },
108  { "CPU_ZNVER4_FLAGS",
109    "CPU_ZNVER3_FLAGS|CpuAVX512F|CpuAVX512DQ|CpuAVX512IFMA|CpuAVX512CD|CpuAVX512BW|CpuAVX512VL|CpuAVX512_BF16|CpuAVX512VBMI|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_VPOPCNTDQ|CpuGFNI|CpuRMPQUERY" },
110  { "CPU_BTVER1_FLAGS",
111    "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME" },
112  { "CPU_BTVER2_FLAGS",
113    "CPU_BTVER1_FLAGS|CPU_AVX_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuMovbe|CpuXsaveopt|CpuPRFCHW" },
114  { "CPU_8087_FLAGS",
115    "Cpu8087" },
116  { "CPU_287_FLAGS",
117    "Cpu287" },
118  { "CPU_387_FLAGS",
119    "Cpu387" },
120  { "CPU_687_FLAGS",
121    "CPU_387_FLAGS|Cpu687" },
122  { "CPU_CMOV_FLAGS",
123    "CpuCMOV" },
124  { "CPU_FXSR_FLAGS",
125    "CpuFXSR" },
126  { "CPU_CLFLUSH_FLAGS",
127    "CpuClflush" },
128  { "CPU_NOP_FLAGS",
129    "CpuNop" },
130  { "CPU_SYSCALL_FLAGS",
131    "CpuSYSCALL" },
132  { "CPU_MMX_FLAGS",
133    "CpuMMX" },
134  { "CPU_SSE_FLAGS",
135    "CpuSSE" },
136  { "CPU_SSE2_FLAGS",
137    "CPU_SSE_FLAGS|CpuSSE2" },
138  { "CPU_SSE3_FLAGS",
139    "CPU_SSE2_FLAGS|CpuSSE3" },
140  { "CPU_SSSE3_FLAGS",
141    "CPU_SSE3_FLAGS|CpuSSSE3" },
142  { "CPU_SSE4_1_FLAGS",
143    "CPU_SSSE3_FLAGS|CpuSSE4_1" },
144  { "CPU_SSE4_2_FLAGS",
145    "CPU_SSE4_1_FLAGS|CpuSSE4_2|CpuPOPCNT" },
146  { "CPU_VMX_FLAGS",
147    "CpuVMX" },
148  { "CPU_SMX_FLAGS",
149    "CpuSMX" },
150  { "CPU_XSAVE_FLAGS",
151    "CpuXsave" },
152  { "CPU_XSAVEOPT_FLAGS",
153    "CPU_XSAVE_FLAGS|CpuXsaveopt" },
154  { "CPU_AES_FLAGS",
155    "CPU_SSE2_FLAGS|CpuAES" },
156  { "CPU_PCLMUL_FLAGS",
157    "CPU_SSE2_FLAGS|CpuPCLMUL" },
158  { "CPU_FMA_FLAGS",
159    "CPU_AVX_FLAGS|CpuFMA" },
160  { "CPU_FMA4_FLAGS",
161    "CPU_AVX_FLAGS|CpuFMA4" },
162  { "CPU_XOP_FLAGS",
163    "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
164  { "CPU_LWP_FLAGS",
165    "CPU_XSAVE_FLAGS|CpuLWP" },
166  { "CPU_BMI_FLAGS",
167    "CpuBMI" },
168  { "CPU_TBM_FLAGS",
169    "CpuTBM" },
170  { "CPU_MOVBE_FLAGS",
171    "CpuMovbe" },
172  { "CPU_CX16_FLAGS",
173    "CpuCX16" },
174  { "CPU_RDTSCP_FLAGS",
175    "CpuRdtscp" },
176  { "CPU_EPT_FLAGS",
177    "CpuEPT" },
178  { "CPU_FSGSBASE_FLAGS",
179    "CpuFSGSBase" },
180  { "CPU_RDRND_FLAGS",
181    "CpuRdRnd" },
182  { "CPU_F16C_FLAGS",
183    "CPU_AVX_FLAGS|CpuF16C" },
184  { "CPU_BMI2_FLAGS",
185    "CpuBMI2" },
186  { "CPU_LZCNT_FLAGS",
187    "CpuLZCNT" },
188  { "CPU_POPCNT_FLAGS",
189    "CpuPOPCNT" },
190  { "CPU_HLE_FLAGS",
191    "CpuHLE" },
192  { "CPU_RTM_FLAGS",
193    "CpuRTM" },
194  { "CPU_INVPCID_FLAGS",
195    "CpuINVPCID" },
196  { "CPU_VMFUNC_FLAGS",
197    "CpuVMFUNC" },
198  { "CPU_3DNOW_FLAGS",
199    "CPU_MMX_FLAGS|Cpu3dnow" },
200  { "CPU_3DNOWA_FLAGS",
201    "CPU_3DNOW_FLAGS|Cpu3dnowA" },
202  { "CPU_PADLOCK_FLAGS",
203    "CpuPadLock" },
204  { "CPU_SVME_FLAGS",
205    "CpuSVME" },
206  { "CPU_SSE4A_FLAGS",
207    "CPU_SSE3_FLAGS|CpuSSE4a" },
208  { "CPU_ABM_FLAGS",
209    "CpuLZCNT|CpuPOPCNT" },
210  { "CPU_AVX_FLAGS",
211    "CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
212  { "CPU_AVX2_FLAGS",
213    "CPU_AVX_FLAGS|CpuAVX2" },
214  { "CPU_AVX_VNNI_FLAGS",
215    "CPU_AVX2_FLAGS|CpuAVX_VNNI" },
216  { "CPU_AVX512F_FLAGS",
217    "CPU_AVX2_FLAGS|CpuAVX512F" },
218  { "CPU_AVX512CD_FLAGS",
219    "CPU_AVX512F_FLAGS|CpuAVX512CD" },
220  { "CPU_AVX512ER_FLAGS",
221    "CPU_AVX512F_FLAGS|CpuAVX512ER" },
222  { "CPU_AVX512PF_FLAGS",
223    "CPU_AVX512F_FLAGS|CpuAVX512PF" },
224  { "CPU_AVX512DQ_FLAGS",
225    "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
226  { "CPU_AVX512BW_FLAGS",
227    "CPU_AVX512F_FLAGS|CpuAVX512BW" },
228  { "CPU_AVX512VL_FLAGS",
229    "CPU_AVX512F_FLAGS|CpuAVX512VL" },
230  { "CPU_AVX512IFMA_FLAGS",
231    "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
232  { "CPU_AVX512VBMI_FLAGS",
233    "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
234  { "CPU_AVX512_4FMAPS_FLAGS",
235    "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
236  { "CPU_AVX512_4VNNIW_FLAGS",
237    "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
238  { "CPU_AVX512_VPOPCNTDQ_FLAGS",
239    "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
240  { "CPU_AVX512_VBMI2_FLAGS",
241    "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
242  { "CPU_AVX512_VNNI_FLAGS",
243    "CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
244  { "CPU_AVX512_BITALG_FLAGS",
245    "CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
246  { "CPU_AVX512_BF16_FLAGS",
247    "CPU_AVX512F_FLAGS|CpuAVX512_BF16" },
248  { "CPU_AVX512_FP16_FLAGS",
249    "CPU_AVX512BW_FLAGS|CpuAVX512_FP16" },
250  { "CPU_PREFETCHI_FLAGS",
251    "CpuPREFETCHI"},
252  { "CPU_AVX_IFMA_FLAGS",
253    "CPU_AVX2_FLAGS|CpuAVX_IFMA" },
254  { "CPU_AVX_VNNI_INT8_FLAGS",
255    "CPU_AVX2_FLAGS|CpuAVX_VNNI_INT8" },
256  { "CPU_CMPCCXADD_FLAGS",
257    "CpuCMPCCXADD" },
258  { "CPU_WRMSRNS_FLAGS",
259    "CpuWRMSRNS" },
260  { "CPU_MSRLIST_FLAGS",
261    "CpuMSRLIST" },
262  { "CPU_AVX_NE_CONVERT_FLAGS",
263    "CPU_AVX2_FLAGS|CpuAVX_NE_CONVERT" },
264  { "CPU_RAO_INT_FLAGS",
265    "CpuRAO_INT" },
266  { "CPU_IAMCU_FLAGS",
267    "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
268  { "CPU_ADX_FLAGS",
269    "CpuADX" },
270  { "CPU_RDSEED_FLAGS",
271    "CpuRdSeed" },
272  { "CPU_PRFCHW_FLAGS",
273    "CpuPRFCHW" },
274  { "CPU_SMAP_FLAGS",
275    "CpuSMAP" },
276  { "CPU_MPX_FLAGS",
277    "CPU_XSAVE_FLAGS|CpuMPX" },
278  { "CPU_SHA_FLAGS",
279    "CPU_SSE2_FLAGS|CpuSHA" },
280  { "CPU_CLFLUSHOPT_FLAGS",
281    "CpuClflushOpt" },
282  { "CPU_XSAVES_FLAGS",
283    "CPU_XSAVE_FLAGS|CpuXSAVES" },
284  { "CPU_XSAVEC_FLAGS",
285    "CPU_XSAVE_FLAGS|CpuXSAVEC" },
286  { "CPU_PREFETCHWT1_FLAGS",
287    "CpuPREFETCHWT1" },
288  { "CPU_SE1_FLAGS",
289    "CpuSE1" },
290  { "CPU_CLWB_FLAGS",
291    "CpuCLWB" },
292  { "CPU_CLZERO_FLAGS",
293    "CpuCLZERO" },
294  { "CPU_MWAITX_FLAGS",
295    "CpuMWAITX" },
296  { "CPU_OSPKE_FLAGS",
297    "CPU_XSAVE_FLAGS|CpuOSPKE" },
298  { "CPU_RDPID_FLAGS",
299    "CpuRDPID" },
300  { "CPU_PTWRITE_FLAGS",
301    "CpuPTWRITE" },
302  { "CPU_IBT_FLAGS",
303    "CpuIBT" },
304  { "CPU_SHSTK_FLAGS",
305    "CpuSHSTK" },
306  { "CPU_GFNI_FLAGS",
307    "CpuGFNI" },
308  { "CPU_VAES_FLAGS",
309    "CpuVAES" },
310  { "CPU_VPCLMULQDQ_FLAGS",
311    "CpuVPCLMULQDQ" },
312  { "CPU_WBNOINVD_FLAGS",
313    "CpuWBNOINVD" },
314  { "CPU_PCONFIG_FLAGS",
315    "CpuPCONFIG" },
316  { "CPU_WAITPKG_FLAGS",
317    "CpuWAITPKG" },
318  { "CPU_UINTR_FLAGS",
319    "CpuUINTR" },
320  { "CPU_CLDEMOTE_FLAGS",
321    "CpuCLDEMOTE" },
322  { "CPU_AMX_INT8_FLAGS",
323    "CPU_AMX_TILE_FLAGS|CpuAMX_INT8" },
324  { "CPU_AMX_BF16_FLAGS",
325    "CPU_AMX_TILE_FLAGS|CpuAMX_BF16" },
326  { "CPU_AMX_FP16_FLAGS",
327    "CPU_AMX_TILE_FLAGS|CpuAMX_FP16" },
328  { "CPU_AMX_TILE_FLAGS",
329    "CpuAMX_TILE" },
330  { "CPU_MOVDIRI_FLAGS",
331    "CpuMOVDIRI" },
332  { "CPU_MOVDIR64B_FLAGS",
333    "CpuMOVDIR64B" },
334  { "CPU_ENQCMD_FLAGS",
335    "CpuENQCMD" },
336  { "CPU_SERIALIZE_FLAGS",
337    "CpuSERIALIZE" },
338  { "CPU_AVX512_VP2INTERSECT_FLAGS",
339    "CpuAVX512_VP2INTERSECT" },
340  { "CPU_TDX_FLAGS",
341    "CpuTDX" },
342  { "CPU_RDPRU_FLAGS",
343    "CpuRDPRU" },
344  { "CPU_MCOMMIT_FLAGS",
345    "CpuMCOMMIT" },
346  { "CPU_SEV_ES_FLAGS",
347    "CpuSEV_ES" },
348  { "CPU_TSXLDTRK_FLAGS",
349    "CpuTSXLDTRK"},
350  { "CPU_KL_FLAGS",
351    "CpuKL" },
352  { "CPU_WIDEKL_FLAGS",
353    "CpuWideKL" },
354  { "CPU_HRESET_FLAGS",
355    "CpuHRESET"},
356  { "CPU_INVLPGB_FLAGS",
357    "CpuINVLPGB" },
358  { "CPU_TLBSYNC_FLAGS",
359    "CpuTLBSYNC" },
360  { "CPU_SNP_FLAGS",
361    "CpuSNP" },
362  { "CPU_RMPQUERY_FLAGS",
363    "CpuRMPQUERY" },
364  { "CPU_ANY_X87_FLAGS",
365    "CPU_ANY_287_FLAGS|Cpu8087" },
366  { "CPU_ANY_287_FLAGS",
367    "CPU_ANY_387_FLAGS|Cpu287" },
368  { "CPU_ANY_387_FLAGS",
369    "CPU_ANY_687_FLAGS|Cpu387" },
370  { "CPU_ANY_687_FLAGS",
371    "Cpu687|CpuFISTTP" },
372  { "CPU_ANY_CMOV_FLAGS",
373    "CpuCMOV" },
374  { "CPU_ANY_FXSR_FLAGS",
375    "CpuFXSR" },
376  { "CPU_ANY_MMX_FLAGS",
377    "CPU_3DNOWA_FLAGS" },
378  { "CPU_ANY_SSE_FLAGS",
379    "CPU_ANY_SSE2_FLAGS|CpuSSE" },
380  { "CPU_ANY_SSE2_FLAGS",
381    "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
382  { "CPU_ANY_SSE3_FLAGS",
383    "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
384  { "CPU_ANY_SSSE3_FLAGS",
385    "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
386  { "CPU_ANY_SSE4_1_FLAGS",
387    "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
388  { "CPU_ANY_SSE4_2_FLAGS",
389    "CpuSSE4_2" },
390  { "CPU_ANY_SSE4A_FLAGS",
391    "CpuSSE4a" },
392  { "CPU_ANY_AVX_FLAGS",
393    "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
394  { "CPU_ANY_AVX2_FLAGS",
395    "CPU_ANY_AVX512F_FLAGS|CpuAVX2|CpuAVX_VNNI|CpuAVX_IFMA|CpuAVX_VNNI_INT8|CpuAVX_NE_CONVERT" },
396  { "CPU_ANY_AVX512F_FLAGS",
397    "CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CPU_ANY_AVX512BW_FLAGS|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_BF16|CpuAVX512_VP2INTERSECT" },
398  { "CPU_ANY_AVX512CD_FLAGS",
399    "CpuAVX512CD" },
400  { "CPU_ANY_AVX512ER_FLAGS",
401    "CpuAVX512ER" },
402  { "CPU_ANY_AVX512PF_FLAGS",
403    "CpuAVX512PF" },
404  { "CPU_ANY_AVX512DQ_FLAGS",
405    "CpuAVX512DQ" },
406  { "CPU_ANY_AVX512BW_FLAGS",
407    "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
408  { "CPU_ANY_AVX512VL_FLAGS",
409    "CpuAVX512VL" },
410  { "CPU_ANY_AVX512IFMA_FLAGS",
411    "CpuAVX512IFMA" },
412  { "CPU_ANY_AVX512VBMI_FLAGS",
413    "CpuAVX512VBMI" },
414  { "CPU_ANY_AVX512_4FMAPS_FLAGS",
415    "CpuAVX512_4FMAPS" },
416  { "CPU_ANY_AVX512_4VNNIW_FLAGS",
417    "CpuAVX512_4VNNIW" },
418  { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
419    "CpuAVX512_VPOPCNTDQ" },
420  { "CPU_ANY_IBT_FLAGS",
421    "CpuIBT" },
422  { "CPU_ANY_SHSTK_FLAGS",
423    "CpuSHSTK" },
424  { "CPU_ANY_AVX512_VBMI2_FLAGS",
425    "CpuAVX512_VBMI2" },
426  { "CPU_ANY_AVX512_VNNI_FLAGS",
427    "CpuAVX512_VNNI" },
428  { "CPU_ANY_AVX512_BITALG_FLAGS",
429    "CpuAVX512_BITALG" },
430  { "CPU_ANY_AVX512_BF16_FLAGS",
431    "CpuAVX512_BF16" },
432  { "CPU_ANY_AMX_INT8_FLAGS",
433    "CpuAMX_INT8" },
434  { "CPU_ANY_AMX_BF16_FLAGS",
435    "CpuAMX_BF16" },
436  { "CPU_ANY_AMX_TILE_FLAGS",
437    "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16|CpuAMX_FP16" },
438  { "CPU_ANY_AVX_VNNI_FLAGS",
439    "CpuAVX_VNNI" },
440  { "CPU_ANY_MOVDIRI_FLAGS",
441    "CpuMOVDIRI" },
442  { "CPU_ANY_UINTR_FLAGS",
443    "CpuUINTR" },
444  { "CPU_ANY_MOVDIR64B_FLAGS",
445    "CpuMOVDIR64B" },
446  { "CPU_ANY_ENQCMD_FLAGS",
447    "CpuENQCMD" },
448  { "CPU_ANY_SERIALIZE_FLAGS",
449    "CpuSERIALIZE" },
450  { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
451    "CpuAVX512_VP2INTERSECT" },
452  { "CPU_ANY_TDX_FLAGS",
453    "CpuTDX" },
454  { "CPU_ANY_TSXLDTRK_FLAGS",
455    "CpuTSXLDTRK" },
456  { "CPU_ANY_KL_FLAGS",
457    "CpuKL|CpuWideKL" },
458  { "CPU_ANY_WIDEKL_FLAGS",
459    "CpuWideKL" },
460  { "CPU_ANY_HRESET_FLAGS",
461    "CpuHRESET" },
462  { "CPU_ANY_AVX512_FP16_FLAGS",
463    "CpuAVX512_FP16" },
464  { "CPU_ANY_AVX_IFMA_FLAGS",
465    "CpuAVX_IFMA" },
466  { "CPU_ANY_AVX_VNNI_INT8_FLAGS",
467    "CpuAVX_VNNI_INT8" },
468  { "CPU_ANY_CMPCCXADD_FLAGS",
469    "CpuCMPCCXADD" },
470  { "CPU_ANY_WRMSRNS_FLAGS",
471    "CpuWRMSRNS" },
472  { "CPU_ANY_MSRLIST_FLAGS",
473    "CpuMSRLIST" },
474  { "CPU_ANY_AVX_NE_CONVERT_FLAGS",
475    "CpuAVX_NE_CONVERT" },
476  { "CPU_ANY_RAO_INT_FLAGS",
477    "CpuRAO_INT"},
478};
479
480typedef struct bitfield
481{
482  int position;
483  int value;
484  const char *name;
485} bitfield;
486
487#define BITFIELD(n) { n, 0, #n }
488
489static bitfield cpu_flags[] =
490{
491  BITFIELD (Cpu186),
492  BITFIELD (Cpu286),
493  BITFIELD (Cpu386),
494  BITFIELD (Cpu486),
495  BITFIELD (Cpu586),
496  BITFIELD (Cpu686),
497  BITFIELD (CpuCMOV),
498  BITFIELD (CpuFXSR),
499  BITFIELD (CpuClflush),
500  BITFIELD (CpuNop),
501  BITFIELD (CpuSYSCALL),
502  BITFIELD (Cpu8087),
503  BITFIELD (Cpu287),
504  BITFIELD (Cpu387),
505  BITFIELD (Cpu687),
506  BITFIELD (CpuFISTTP),
507  BITFIELD (CpuMMX),
508  BITFIELD (CpuSSE),
509  BITFIELD (CpuSSE2),
510  BITFIELD (CpuSSE3),
511  BITFIELD (CpuSSSE3),
512  BITFIELD (CpuSSE4_1),
513  BITFIELD (CpuSSE4_2),
514  BITFIELD (CpuAVX),
515  BITFIELD (CpuAVX2),
516  BITFIELD (CpuAVX512F),
517  BITFIELD (CpuAVX512CD),
518  BITFIELD (CpuAVX512ER),
519  BITFIELD (CpuAVX512PF),
520  BITFIELD (CpuAVX512VL),
521  BITFIELD (CpuAVX512DQ),
522  BITFIELD (CpuAVX512BW),
523  BITFIELD (CpuIAMCU),
524  BITFIELD (CpuSSE4a),
525  BITFIELD (Cpu3dnow),
526  BITFIELD (Cpu3dnowA),
527  BITFIELD (CpuPadLock),
528  BITFIELD (CpuSVME),
529  BITFIELD (CpuVMX),
530  BITFIELD (CpuSMX),
531  BITFIELD (CpuXsave),
532  BITFIELD (CpuXsaveopt),
533  BITFIELD (CpuAES),
534  BITFIELD (CpuPCLMUL),
535  BITFIELD (CpuFMA),
536  BITFIELD (CpuFMA4),
537  BITFIELD (CpuXOP),
538  BITFIELD (CpuLWP),
539  BITFIELD (CpuBMI),
540  BITFIELD (CpuTBM),
541  BITFIELD (CpuLM),
542  BITFIELD (CpuMovbe),
543  BITFIELD (CpuCX16),
544  BITFIELD (CpuEPT),
545  BITFIELD (CpuRdtscp),
546  BITFIELD (CpuFSGSBase),
547  BITFIELD (CpuRdRnd),
548  BITFIELD (CpuF16C),
549  BITFIELD (CpuBMI2),
550  BITFIELD (CpuLZCNT),
551  BITFIELD (CpuPOPCNT),
552  BITFIELD (CpuHLE),
553  BITFIELD (CpuRTM),
554  BITFIELD (CpuINVPCID),
555  BITFIELD (CpuVMFUNC),
556  BITFIELD (CpuRDSEED),
557  BITFIELD (CpuADX),
558  BITFIELD (CpuPRFCHW),
559  BITFIELD (CpuSMAP),
560  BITFIELD (CpuSHA),
561  BITFIELD (CpuClflushOpt),
562  BITFIELD (CpuXSAVES),
563  BITFIELD (CpuXSAVEC),
564  BITFIELD (CpuPREFETCHWT1),
565  BITFIELD (CpuSE1),
566  BITFIELD (CpuCLWB),
567  BITFIELD (CpuMPX),
568  BITFIELD (CpuAVX512IFMA),
569  BITFIELD (CpuAVX512VBMI),
570  BITFIELD (CpuAVX512_4FMAPS),
571  BITFIELD (CpuAVX512_4VNNIW),
572  BITFIELD (CpuAVX512_VPOPCNTDQ),
573  BITFIELD (CpuAVX512_VBMI2),
574  BITFIELD (CpuAVX512_VNNI),
575  BITFIELD (CpuAVX512_BITALG),
576  BITFIELD (CpuAVX512_BF16),
577  BITFIELD (CpuAVX512_VP2INTERSECT),
578  BITFIELD (CpuTDX),
579  BITFIELD (CpuAVX_VNNI),
580  BITFIELD (CpuAVX512_FP16),
581  BITFIELD (CpuPREFETCHI),
582  BITFIELD (CpuAVX_IFMA),
583  BITFIELD (CpuAVX_VNNI_INT8),
584  BITFIELD (CpuCMPCCXADD),
585  BITFIELD (CpuWRMSRNS),
586  BITFIELD (CpuMSRLIST),
587  BITFIELD (CpuAVX_NE_CONVERT),
588  BITFIELD (CpuRAO_INT),
589  BITFIELD (CpuMWAITX),
590  BITFIELD (CpuCLZERO),
591  BITFIELD (CpuOSPKE),
592  BITFIELD (CpuRDPID),
593  BITFIELD (CpuPTWRITE),
594  BITFIELD (CpuIBT),
595  BITFIELD (CpuSHSTK),
596  BITFIELD (CpuGFNI),
597  BITFIELD (CpuVAES),
598  BITFIELD (CpuVPCLMULQDQ),
599  BITFIELD (CpuWBNOINVD),
600  BITFIELD (CpuPCONFIG),
601  BITFIELD (CpuWAITPKG),
602  BITFIELD (CpuUINTR),
603  BITFIELD (CpuCLDEMOTE),
604  BITFIELD (CpuAMX_INT8),
605  BITFIELD (CpuAMX_BF16),
606  BITFIELD (CpuAMX_FP16),
607  BITFIELD (CpuAMX_TILE),
608  BITFIELD (CpuMOVDIRI),
609  BITFIELD (CpuMOVDIR64B),
610  BITFIELD (CpuENQCMD),
611  BITFIELD (CpuSERIALIZE),
612  BITFIELD (CpuRDPRU),
613  BITFIELD (CpuMCOMMIT),
614  BITFIELD (CpuSEV_ES),
615  BITFIELD (CpuTSXLDTRK),
616  BITFIELD (CpuKL),
617  BITFIELD (CpuWideKL),
618  BITFIELD (CpuHRESET),
619  BITFIELD (CpuINVLPGB),
620  BITFIELD (CpuTLBSYNC),
621  BITFIELD (CpuSNP),
622  BITFIELD (CpuRMPQUERY),
623  BITFIELD (Cpu64),
624  BITFIELD (CpuNo64),
625#ifdef CpuUnused
626  BITFIELD (CpuUnused),
627#endif
628};
629
630static bitfield opcode_modifiers[] =
631{
632  BITFIELD (D),
633  BITFIELD (W),
634  BITFIELD (Load),
635  BITFIELD (Modrm),
636  BITFIELD (Jump),
637  BITFIELD (FloatMF),
638  BITFIELD (Size),
639  BITFIELD (CheckRegSize),
640  BITFIELD (OperandConstraint),
641  BITFIELD (MnemonicSize),
642  BITFIELD (No_bSuf),
643  BITFIELD (No_wSuf),
644  BITFIELD (No_lSuf),
645  BITFIELD (No_sSuf),
646  BITFIELD (No_qSuf),
647  BITFIELD (FWait),
648  BITFIELD (IsString),
649  BITFIELD (RegMem),
650  BITFIELD (BNDPrefixOk),
651  BITFIELD (PrefixOk),
652  BITFIELD (IsPrefix),
653  BITFIELD (ImmExt),
654  BITFIELD (NoRex64),
655  BITFIELD (Vex),
656  BITFIELD (VexVVVV),
657  BITFIELD (VexW),
658  BITFIELD (OpcodeSpace),
659  BITFIELD (OpcodePrefix),
660  BITFIELD (VexSources),
661  BITFIELD (SIB),
662  BITFIELD (SSE2AVX),
663  BITFIELD (EVex),
664  BITFIELD (Masking),
665  BITFIELD (Broadcast),
666  BITFIELD (StaticRounding),
667  BITFIELD (SAE),
668  BITFIELD (Disp8MemShift),
669  BITFIELD (Optimize),
670  BITFIELD (ATTMnemonic),
671  BITFIELD (ATTSyntax),
672  BITFIELD (IntelSyntax),
673  BITFIELD (ISA64),
674};
675
676#define CLASS(n) #n, n
677
678static const struct {
679  const char *name;
680  enum operand_class value;
681} operand_classes[] = {
682  CLASS (Reg),
683  CLASS (SReg),
684  CLASS (RegCR),
685  CLASS (RegDR),
686  CLASS (RegTR),
687  CLASS (RegMMX),
688  CLASS (RegSIMD),
689  CLASS (RegMask),
690  CLASS (RegBND),
691};
692
693#undef CLASS
694
695#define INSTANCE(n) #n, n
696
697static const struct {
698  const char *name;
699  enum operand_instance value;
700} operand_instances[] = {
701    INSTANCE (Accum),
702    INSTANCE (RegC),
703    INSTANCE (RegD),
704    INSTANCE (RegB),
705};
706
707#undef INSTANCE
708
709static bitfield operand_types[] =
710{
711  BITFIELD (Imm1),
712  BITFIELD (Imm8),
713  BITFIELD (Imm8S),
714  BITFIELD (Imm16),
715  BITFIELD (Imm32),
716  BITFIELD (Imm32S),
717  BITFIELD (Imm64),
718  BITFIELD (BaseIndex),
719  BITFIELD (Disp8),
720  BITFIELD (Disp16),
721  BITFIELD (Disp32),
722  BITFIELD (Disp64),
723  BITFIELD (Byte),
724  BITFIELD (Word),
725  BITFIELD (Dword),
726  BITFIELD (Fword),
727  BITFIELD (Qword),
728  BITFIELD (Tbyte),
729  BITFIELD (Xmmword),
730  BITFIELD (Ymmword),
731  BITFIELD (Zmmword),
732  BITFIELD (Tmmword),
733  BITFIELD (Unspecified),
734#ifdef OTUnused
735  BITFIELD (OTUnused),
736#endif
737};
738
739static const char *filename;
740static i386_cpu_flags active_cpu_flags;
741static int active_isstring;
742
743struct template_arg {
744  const struct template_arg *next;
745  const char *val;
746};
747
748struct template_instance {
749  const struct template_instance *next;
750  const char *name;
751  const struct template_arg *args;
752};
753
754struct template_param {
755  const struct template_param *next;
756  const char *name;
757};
758
759struct template {
760  struct template *next;
761  const char *name;
762  const struct template_instance *instances;
763  const struct template_param *params;
764};
765
766static struct template *templates;
767
768static int
769compare (const void *x, const void *y)
770{
771  const bitfield *xp = (const bitfield *) x;
772  const bitfield *yp = (const bitfield *) y;
773  return xp->position - yp->position;
774}
775
776static void
777fail (const char *message, ...)
778{
779  va_list args;
780
781  va_start (args, message);
782  fprintf (stderr, _("%s: error: "), program_name);
783  vfprintf (stderr, message, args);
784  va_end (args);
785  xexit (1);
786}
787
788static void
789process_copyright (FILE *fp)
790{
791  fprintf (fp, "/* This file is automatically generated by i386-gen.  Do not edit!  */\n\
792/* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
793\n\
794   This file is part of the GNU opcodes library.\n\
795\n\
796   This library is free software; you can redistribute it and/or modify\n\
797   it under the terms of the GNU General Public License as published by\n\
798   the Free Software Foundation; either version 3, or (at your option)\n\
799   any later version.\n\
800\n\
801   It is distributed in the hope that it will be useful, but WITHOUT\n\
802   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
803   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\n\
804   License for more details.\n\
805\n\
806   You should have received a copy of the GNU General Public License\n\
807   along with this program; if not, write to the Free Software\n\
808   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
809   MA 02110-1301, USA.  */\n");
810}
811
812/* Remove leading white spaces.  */
813
814static char *
815remove_leading_whitespaces (char *str)
816{
817  while (ISSPACE (*str))
818    str++;
819  return str;
820}
821
822/* Remove trailing white spaces.  */
823
824static void
825remove_trailing_whitespaces (char *str)
826{
827  size_t last = strlen (str);
828
829  if (last == 0)
830    return;
831
832  do
833    {
834      last--;
835      if (ISSPACE (str [last]))
836	str[last] = '\0';
837      else
838	break;
839    }
840  while (last != 0);
841}
842
843/* Find next field separated by SEP and terminate it. Return a
844   pointer to the one after it.  */
845
846static char *
847next_field (char *str, char sep, char **next, char *last)
848{
849  char *p;
850
851  p = remove_leading_whitespaces (str);
852  for (str = p; *str != sep && *str != '\0'; str++);
853
854  *str = '\0';
855  remove_trailing_whitespaces (p);
856
857  *next = str + 1;
858
859  if (p >= last)
860    abort ();
861
862  return p;
863}
864
865static void set_bitfield (char *, bitfield *, int, unsigned int, int);
866
867static int
868set_bitfield_from_cpu_flag_init (char *f, bitfield *array, unsigned int size,
869				 int lineno)
870{
871  char *str, *next, *last;
872  unsigned int i;
873
874  for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
875    if (strcmp (cpu_flag_init[i].name, f) == 0)
876      {
877	/* Turn on selective bits.  */
878	char *init = xstrdup (cpu_flag_init[i].init);
879	last = init + strlen (init);
880	for (next = init; next && next < last; )
881	  {
882	    str = next_field (next, '|', &next, last);
883	    if (str)
884	      set_bitfield (str, array, 1, size, lineno);
885	  }
886	free (init);
887	return 0;
888      }
889
890  return -1;
891}
892
893static void
894set_bitfield (char *f, bitfield *array, int value,
895	      unsigned int size, int lineno)
896{
897  unsigned int i;
898
899  /* Ignore empty fields; they may result from template expansions.  */
900  if (*f == '\0')
901    return;
902
903  for (i = 0; i < size; i++)
904    if (strcasecmp (array[i].name, f) == 0)
905      {
906	array[i].value = value;
907	return;
908      }
909
910  if (value)
911    {
912      const char *v = strchr (f, '=');
913
914      if (v)
915	{
916	  size_t n = v - f;
917	  char *end;
918
919	  for (i = 0; i < size; i++)
920	    if (strncasecmp (array[i].name, f, n) == 0)
921	      {
922		value = strtol (v + 1, &end, 0);
923		if (*end == '\0')
924		  {
925		    array[i].value = value;
926		    return;
927		  }
928		break;
929	      }
930	}
931    }
932
933  /* Handle CPU_XXX_FLAGS.  */
934  if (value == 1 && !set_bitfield_from_cpu_flag_init (f, array, size, lineno))
935    return;
936
937  if (lineno != -1)
938    fail (_("%s: %d: unknown bitfield: %s\n"), filename, lineno, f);
939  else
940    fail (_("unknown bitfield: %s\n"), f);
941}
942
943static void
944output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
945		  int macro, const char *comma, const char *indent)
946{
947  unsigned int i;
948
949  memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
950
951  fprintf (table, "%s{ { ", indent);
952
953  for (i = 0; i < size - 1; i++)
954    {
955      if (((i + 1) % 20) != 0)
956	fprintf (table, "%d, ", flags[i].value);
957      else
958	fprintf (table, "%d,", flags[i].value);
959      if (((i + 1) % 20) == 0)
960	{
961	  /* We need \\ for macro.  */
962	  if (macro)
963	    fprintf (table, " \\\n    %s", indent);
964	  else
965	    fprintf (table, "\n    %s", indent);
966	}
967      if (flags[i].value)
968	active_cpu_flags.array[i / 32] |= 1U << (i % 32);
969    }
970
971  fprintf (table, "%d } }%s\n", flags[i].value, comma);
972}
973
974static void
975process_i386_cpu_flag (FILE *table, char *flag, int macro,
976		       const char *comma, const char *indent,
977		       int lineno)
978{
979  char *str, *next = flag, *last;
980  unsigned int i;
981  int value = 1;
982  bitfield flags [ARRAY_SIZE (cpu_flags)];
983
984  /* Copy the default cpu flags.  */
985  memcpy (flags, cpu_flags, sizeof (cpu_flags));
986
987  if (flag[0] == '~')
988    {
989      last = flag + strlen (flag);
990
991      if (flag[1] == '(')
992	{
993	  last -= 1;
994	  next = flag + 2;
995	  if (*last != ')')
996	    fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename,
997		  lineno, flag);
998	  *last = '\0';
999	}
1000      else
1001	next = flag + 1;
1002
1003      /* First we turn on everything except for cpu64, cpuno64, and - if
1004         present - the padding field.  */
1005      for (i = 0; i < ARRAY_SIZE (flags); i++)
1006	if (flags[i].position < Cpu64)
1007	  flags[i].value = 1;
1008
1009      /* Turn off selective bits.  */
1010      value = 0;
1011    }
1012
1013  if (strcmp (flag, "0"))
1014    {
1015      /* Turn on/off selective bits.  */
1016      last = flag + strlen (flag);
1017      for (; next && next < last; )
1018	{
1019	  str = next_field (next, '|', &next, last);
1020	  if (str)
1021	    set_bitfield (str, flags, value, ARRAY_SIZE (flags), lineno);
1022	}
1023    }
1024
1025  output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
1026		    comma, indent);
1027}
1028
1029static void
1030output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
1031{
1032  unsigned int i;
1033
1034  fprintf (table, "    { ");
1035
1036  for (i = 0; i < size - 1; i++)
1037    {
1038      if (((i + 1) % 20) != 0)
1039        fprintf (table, "%d, ", modifier[i].value);
1040      else
1041        fprintf (table, "%d,", modifier[i].value);
1042      if (((i + 1) % 20) == 0)
1043	fprintf (table, "\n      ");
1044    }
1045
1046  fprintf (table, "%d },\n", modifier[i].value);
1047}
1048
1049/* Returns LOG2 of element size.  */
1050static int
1051get_element_size (char **opnd, int lineno)
1052{
1053  char *str, *next, *last, *op;
1054  const char *full = opnd[0];
1055  int elem_size = INT_MAX;
1056
1057  /* Find the memory operand.  */
1058  while (full != NULL && strstr(full, "BaseIndex") == NULL)
1059    full = *++opnd;
1060  if (full == NULL)
1061    fail (_("%s: %d: no memory operand\n"), filename, lineno);
1062
1063  op = xstrdup (full);
1064  last = op + strlen (op);
1065  for (next = op; next && next < last; )
1066    {
1067      str = next_field (next, '|', &next, last);
1068      if (str)
1069	{
1070	  if (strcasecmp(str, "Byte") == 0)
1071	    {
1072	      /* The smallest element size, no need to check
1073		 further.  */
1074	      elem_size = 0;
1075	      break;
1076	    }
1077	  else if (strcasecmp(str, "Word") == 0)
1078	    {
1079	      if (elem_size > 1)
1080		elem_size = 1;
1081	    }
1082	  else if (strcasecmp(str, "Dword") == 0)
1083	    {
1084	      if (elem_size > 2)
1085		elem_size = 2;
1086	    }
1087	  else if (strcasecmp(str, "Qword") == 0)
1088	    {
1089	      if (elem_size > 3)
1090		elem_size = 3;
1091	    }
1092	}
1093    }
1094  free (op);
1095
1096  if (elem_size == INT_MAX)
1097    fail (_("%s: %d: unknown element size: %s\n"), filename, lineno, full);
1098
1099  return elem_size;
1100}
1101
1102static void
1103process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
1104			      unsigned int prefix, char **opnd, int lineno)
1105{
1106  char *str, *next, *last;
1107  bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
1108
1109  active_isstring = 0;
1110
1111  /* Copy the default opcode modifier.  */
1112  memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
1113
1114  if (strcmp (mod, "0"))
1115    {
1116      unsigned int have_w = 0, bwlq_suf = 0xf;
1117
1118      last = mod + strlen (mod);
1119      for (next = mod; next && next < last; )
1120	{
1121	  str = next_field (next, '|', &next, last);
1122	  if (str)
1123	    {
1124	      int val = 1;
1125	      if (strcasecmp(str, "Broadcast") == 0)
1126		val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
1127	      else if (strcasecmp(str, "Disp8MemShift") == 0)
1128		val = get_element_size (opnd, lineno);
1129
1130	      set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
1131			    lineno);
1132	      if (strcasecmp(str, "IsString") == 0)
1133		active_isstring = 1;
1134
1135	      if (strcasecmp(str, "W") == 0)
1136		have_w = 1;
1137
1138	      if (strcasecmp(str, "No_bSuf") == 0)
1139		bwlq_suf &= ~1;
1140	      if (strcasecmp(str, "No_wSuf") == 0)
1141		bwlq_suf &= ~2;
1142	      if (strcasecmp(str, "No_lSuf") == 0)
1143		bwlq_suf &= ~4;
1144	      if (strcasecmp(str, "No_qSuf") == 0)
1145		bwlq_suf &= ~8;
1146	    }
1147	}
1148
1149      if (space)
1150	{
1151	  if (!modifiers[OpcodeSpace].value)
1152	    modifiers[OpcodeSpace].value = space;
1153	  else if (modifiers[OpcodeSpace].value != space)
1154	    fail (_("%s:%d: Conflicting opcode space specifications\n"),
1155		  filename, lineno);
1156	  else
1157	    fprintf (stderr,
1158		     _("%s:%d: Warning: redundant opcode space specification\n"),
1159		     filename, lineno);
1160	}
1161
1162      if (prefix)
1163	{
1164	  if (!modifiers[OpcodePrefix].value)
1165	    modifiers[OpcodePrefix].value = prefix;
1166	  else if (modifiers[OpcodePrefix].value != prefix)
1167	    fail (_("%s:%d: Conflicting prefix specifications\n"),
1168		  filename, lineno);
1169	  else
1170	    fprintf (stderr,
1171		     _("%s:%d: Warning: redundant prefix specification\n"),
1172		     filename, lineno);
1173	}
1174
1175      if (have_w && !bwlq_suf)
1176	fail ("%s: %d: stray W modifier\n", filename, lineno);
1177      if (have_w && !(bwlq_suf & 1))
1178	fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n",
1179		 filename, lineno);
1180      if (have_w && !(bwlq_suf & ~1))
1181	fprintf (stderr,
1182		 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1183		 filename, lineno);
1184    }
1185  output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
1186}
1187
1188enum stage {
1189  stage_macros,
1190  stage_opcodes,
1191  stage_registers,
1192};
1193
1194static void
1195output_operand_type (FILE *table, enum operand_class class,
1196		     enum operand_instance instance,
1197		     const bitfield *types, unsigned int size,
1198		     enum stage stage, const char *indent)
1199{
1200  unsigned int i;
1201
1202  fprintf (table, "{ { %d, %d, ", class, instance);
1203
1204  for (i = 0; i < size - 1; i++)
1205    {
1206      if (((i + 3) % 20) != 0)
1207	fprintf (table, "%d, ", types[i].value);
1208      else
1209	fprintf (table, "%d,", types[i].value);
1210      if (((i + 3) % 20) == 0)
1211	{
1212	  /* We need \\ for macro.  */
1213	  if (stage == stage_macros)
1214	    fprintf (table, " \\\n%s", indent);
1215	  else
1216	    fprintf (table, "\n%s", indent);
1217	}
1218    }
1219
1220  fprintf (table, "%d } }", types[i].value);
1221}
1222
1223static void
1224process_i386_operand_type (FILE *table, char *op, enum stage stage,
1225			   const char *indent, int lineno)
1226{
1227  char *str, *next, *last;
1228  enum operand_class class = ClassNone;
1229  enum operand_instance instance = InstanceNone;
1230  bitfield types [ARRAY_SIZE (operand_types)];
1231
1232  /* Copy the default operand type.  */
1233  memcpy (types, operand_types, sizeof (types));
1234
1235  if (strcmp (op, "0"))
1236    {
1237      int baseindex = 0;
1238
1239      last = op + strlen (op);
1240      for (next = op; next && next < last; )
1241	{
1242	  str = next_field (next, '|', &next, last);
1243	  if (str)
1244	    {
1245	      unsigned int i;
1246
1247	      if (!strncmp(str, "Class=", 6))
1248		{
1249		  for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
1250		    if (!strcmp(str + 6, operand_classes[i].name))
1251		      {
1252			class = operand_classes[i].value;
1253			str = NULL;
1254			break;
1255		      }
1256		}
1257
1258	      if (str && !strncmp(str, "Instance=", 9))
1259		{
1260		  for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
1261		    if (!strcmp(str + 9, operand_instances[i].name))
1262		      {
1263			instance = operand_instances[i].value;
1264			str = NULL;
1265			break;
1266		      }
1267		}
1268	    }
1269	  if (str)
1270	    {
1271	      set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1272	      if (strcasecmp(str, "BaseIndex") == 0)
1273		baseindex = 1;
1274	    }
1275	}
1276
1277      if (stage == stage_opcodes && baseindex && !active_isstring)
1278	{
1279	  set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno);
1280	  if (!active_cpu_flags.bitfield.cpu64
1281	      && !active_cpu_flags.bitfield.cpumpx)
1282	    set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
1283	  set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
1284	}
1285    }
1286  output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
1287		       stage, indent);
1288}
1289
1290static void
1291output_i386_opcode (FILE *table, const char *name, char *str,
1292		    char *last, int lineno)
1293{
1294  unsigned int i, length, prefix = 0, space = 0;
1295  char *base_opcode, *extension_opcode, *end;
1296  char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1297  unsigned long long opcode;
1298
1299  /* Find base_opcode.  */
1300  base_opcode = next_field (str, ',', &str, last);
1301
1302  /* Find extension_opcode, if any.  */
1303  extension_opcode = strchr (base_opcode, '/');
1304  if (extension_opcode)
1305    *extension_opcode++ = '\0';
1306
1307  /* Find cpu_flags.  */
1308  cpu_flags = next_field (str, ',', &str, last);
1309
1310  /* Find opcode_modifier.  */
1311  opcode_modifier = next_field (str, ',', &str, last);
1312
1313  /* Remove the first {.  */
1314  str = remove_leading_whitespaces (str);
1315  if (*str != '{')
1316    abort ();
1317  str = remove_leading_whitespaces (str + 1);
1318  remove_trailing_whitespaces (str);
1319
1320  /* Remove } and trailing white space. */
1321  i = strlen (str);
1322  if (!i || str[i - 1] != '}')
1323    abort ();
1324  str[--i] = '\0';
1325  remove_trailing_whitespaces (str);
1326
1327  if (!*str)
1328    operand_types [i = 0] = NULL;
1329  else
1330    {
1331      last = str + strlen (str);
1332
1333      /* Find operand_types.  */
1334      for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1335	{
1336	  if (str >= last)
1337	    {
1338	      operand_types [i] = NULL;
1339	      break;
1340	    }
1341
1342	  operand_types [i] = next_field (str, ',', &str, last);
1343	}
1344    }
1345
1346  opcode = strtoull (base_opcode, &end, 0);
1347
1348  /* Determine opcode length.  */
1349  for (length = 1; length < 8; ++length)
1350    if (!(opcode >> (8 * length)))
1351       break;
1352
1353  /* Transform prefixes encoded in the opcode into opcode modifier
1354     representation.  */
1355  if (length > 1)
1356    {
1357      switch (opcode >> (8 * length - 8))
1358	{
1359	case 0x66: prefix = PREFIX_0X66; break;
1360	case 0xF3: prefix = PREFIX_0XF3; break;
1361	case 0xF2: prefix = PREFIX_0XF2; break;
1362	}
1363
1364      if (prefix)
1365	opcode &= (1ULL << (8 * --length)) - 1;
1366    }
1367
1368  /* Transform opcode space encoded in the opcode into opcode modifier
1369     representation.  */
1370  if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
1371    {
1372      switch ((opcode >> (8 * length - 16)) & 0xff)
1373	{
1374	default:   space = SPACE_0F;   break;
1375	case 0x38: space = SPACE_0F38; break;
1376	case 0x3A: space = SPACE_0F3A; break;
1377	}
1378
1379      if (space != SPACE_0F && --length == 1)
1380	fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1381	      filename, lineno, name);
1382      opcode &= (1ULL << (8 * --length)) - 1;
1383    }
1384
1385  if (length > 2)
1386    fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1387	  filename, lineno, name, 2 * length, opcode);
1388
1389  fprintf (table, "  { \"%s\", 0x%0*llx%s, %lu, %s,\n",
1390	   name, 2 * (int)length, opcode, end, i,
1391	   extension_opcode ? extension_opcode : "None");
1392
1393  process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
1394				operand_types, lineno);
1395
1396  process_i386_cpu_flag (table, cpu_flags, 0, ",", "    ", lineno);
1397
1398  fprintf (table, "    { ");
1399
1400  for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1401    {
1402      if (!operand_types[i])
1403	{
1404	  if (i == 0)
1405	    process_i386_operand_type (table, "0", stage_opcodes, "\t  ",
1406				       lineno);
1407	  break;
1408	}
1409
1410      if (i != 0)
1411	fprintf (table, ",\n      ");
1412
1413      process_i386_operand_type (table, operand_types[i], stage_opcodes,
1414				 "\t  ", lineno);
1415    }
1416  fprintf (table, " } },\n");
1417}
1418
1419struct opcode_hash_entry
1420{
1421  struct opcode_hash_entry *next;
1422  char *name;
1423  char *opcode;
1424  int lineno;
1425};
1426
1427/* Calculate the hash value of an opcode hash entry P.  */
1428
1429static hashval_t
1430opcode_hash_hash (const void *p)
1431{
1432  struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1433  return htab_hash_string (entry->name);
1434}
1435
1436/* Compare a string Q against an opcode hash entry P.  */
1437
1438static int
1439opcode_hash_eq (const void *p, const void *q)
1440{
1441  struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1442  const char *name = (const char *) q;
1443  return strcmp (name, entry->name) == 0;
1444}
1445
1446static void
1447parse_template (char *buf, int lineno)
1448{
1449  char sep, *end, *name;
1450  struct template *tmpl;
1451  struct template_instance *last_inst = NULL;
1452
1453  buf = remove_leading_whitespaces (buf + 1);
1454  end = strchr (buf, ':');
1455  if (end == NULL)
1456    {
1457      struct template *prev = NULL;
1458
1459      end = strchr (buf, '>');
1460      if (end == NULL)
1461	fail ("%s: %d: missing ':' or '>'\n", filename, lineno);
1462      if (*remove_leading_whitespaces (end + 1))
1463	fail ("%s: %d: malformed template purge\n", filename, lineno);
1464      *end = '\0';
1465      remove_trailing_whitespaces (buf);
1466      /* Don't bother freeing the various structures.  */
1467      for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next)
1468	if (!strcmp (buf, tmpl->name))
1469	  break;
1470      if (tmpl == NULL)
1471	fail ("%s: %d: no template '%s'\n", filename, lineno, buf);
1472      if (prev)
1473	prev->next = tmpl->next;
1474      else
1475	templates = tmpl->next;
1476      return;
1477    }
1478  *end++ = '\0';
1479  remove_trailing_whitespaces (buf);
1480
1481  if (*buf == '\0')
1482    fail ("%s: %d: missing template identifier\n", filename, lineno);
1483  tmpl = xmalloc (sizeof (*tmpl));
1484  tmpl->name = xstrdup (buf);
1485
1486  tmpl->params = NULL;
1487  do {
1488      struct template_param *param;
1489
1490      buf = remove_leading_whitespaces (end);
1491      end = strpbrk (buf, ":,");
1492      if (end == NULL)
1493        fail ("%s: %d: missing ':' or ','\n", filename, lineno);
1494
1495      sep = *end;
1496      *end++ = '\0';
1497      remove_trailing_whitespaces (buf);
1498
1499      param = xmalloc (sizeof (*param));
1500      param->name = xstrdup (buf);
1501      param->next = tmpl->params;
1502      tmpl->params = param;
1503  } while (sep == ':');
1504
1505  tmpl->instances = NULL;
1506  do {
1507      struct template_instance *inst;
1508      char *cur, *next;
1509      const struct template_param *param;
1510
1511      buf = remove_leading_whitespaces (end);
1512      end = strpbrk (buf, ",>");
1513      if (end == NULL)
1514        fail ("%s: %d: missing ',' or '>'\n", filename, lineno);
1515
1516      sep = *end;
1517      *end++ = '\0';
1518
1519      inst = xmalloc (sizeof (*inst));
1520      inst->next = NULL;
1521      inst->args = NULL;
1522
1523      cur = next_field (buf, ':', &next, end);
1524      inst->name = *cur != '$' ? xstrdup (cur) : "";
1525
1526      for (param = tmpl->params; param; param = param->next)
1527	{
1528	  struct template_arg *arg = xmalloc (sizeof (*arg));
1529
1530	  cur = next_field (next, ':', &next, end);
1531	  if (next > end)
1532	    fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name);
1533	  arg->val = xstrdup (cur);
1534	  arg->next = inst->args;
1535	  inst->args = arg;
1536	}
1537
1538      if (tmpl->instances)
1539	last_inst->next = inst;
1540      else
1541	tmpl->instances = inst;
1542      last_inst = inst;
1543  } while (sep == ',');
1544
1545  buf = remove_leading_whitespaces (end);
1546  if (*buf)
1547    fprintf(stderr, "%s: %d: excess characters '%s'\n",
1548	    filename, lineno, buf);
1549
1550  tmpl->next = templates;
1551  templates = tmpl;
1552}
1553
1554static unsigned int
1555expand_templates (char *name, const char *str, htab_t opcode_hash_table,
1556		  struct opcode_hash_entry ***opcode_array_p, int lineno)
1557{
1558  static unsigned int idx, opcode_array_size;
1559  struct opcode_hash_entry **opcode_array = *opcode_array_p;
1560  struct opcode_hash_entry **hash_slot, **entry;
1561  char *ptr1 = strchr(name, '<'), *ptr2;
1562
1563  if (ptr1 == NULL)
1564    {
1565      /* Get the slot in hash table.  */
1566      hash_slot = (struct opcode_hash_entry **)
1567	htab_find_slot_with_hash (opcode_hash_table, name,
1568				  htab_hash_string (name),
1569				  INSERT);
1570
1571      if (*hash_slot == NULL)
1572	{
1573	  /* It is the new one.  Put it on opcode array.  */
1574	  if (idx >= opcode_array_size)
1575	    {
1576	      /* Grow the opcode array when needed.  */
1577	      opcode_array_size += 1024;
1578	      opcode_array = (struct opcode_hash_entry **)
1579		xrealloc (opcode_array,
1580			  sizeof (*opcode_array) * opcode_array_size);
1581		*opcode_array_p = opcode_array;
1582	    }
1583
1584	  opcode_array[idx] = (struct opcode_hash_entry *)
1585	    xmalloc (sizeof (struct opcode_hash_entry));
1586	  opcode_array[idx]->next = NULL;
1587	  opcode_array[idx]->name = xstrdup (name);
1588	  opcode_array[idx]->opcode = xstrdup (str);
1589	  opcode_array[idx]->lineno = lineno;
1590	  *hash_slot = opcode_array[idx];
1591	  idx++;
1592	}
1593      else
1594	{
1595	  /* Append it to the existing one.  */
1596	  entry = hash_slot;
1597	  while ((*entry) != NULL)
1598	    entry = &(*entry)->next;
1599	  *entry = (struct opcode_hash_entry *)
1600	    xmalloc (sizeof (struct opcode_hash_entry));
1601	  (*entry)->next = NULL;
1602	  (*entry)->name = (*hash_slot)->name;
1603	  (*entry)->opcode = xstrdup (str);
1604	  (*entry)->lineno = lineno;
1605	}
1606    }
1607  else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL)
1608    fail ("%s: %d: missing '>'\n", filename, lineno);
1609  else
1610    {
1611      const struct template *tmpl;
1612      const struct template_instance *inst;
1613
1614      *ptr1 = '\0';
1615      ptr1 = remove_leading_whitespaces (ptr1 + 1);
1616      remove_trailing_whitespaces (ptr1);
1617
1618      *ptr2++ = '\0';
1619
1620      for ( tmpl = templates; tmpl; tmpl = tmpl->next )
1621	if (!strcmp(ptr1, tmpl->name))
1622	  break;
1623      if (!tmpl)
1624	fail ("reference to unknown template '%s'\n", ptr1);
1625
1626      for (inst = tmpl->instances; inst; inst = inst->next)
1627	{
1628	  char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
1629	  char *str2 = xmalloc(2 * strlen(str));
1630	  const char *src;
1631
1632	  strcpy (name2, name);
1633	  strcat (name2, inst->name);
1634	  strcat (name2, ptr2);
1635
1636	  for (ptr1 = str2, src = str; *src; )
1637	    {
1638	      const char *ident = tmpl->name, *end;
1639	      const struct template_param *param;
1640	      const struct template_arg *arg;
1641
1642	      if ((*ptr1 = *src++) != '<')
1643		{
1644		  ++ptr1;
1645		  continue;
1646		}
1647	      while (ISSPACE(*src))
1648		++src;
1649	      while (*ident && *src == *ident)
1650		++src, ++ident;
1651	      while (ISSPACE(*src))
1652		++src;
1653	      if (*src != ':' || *ident != '\0')
1654		{
1655		  memcpy (++ptr1, tmpl->name, ident - tmpl->name);
1656		  ptr1 += ident - tmpl->name;
1657		  continue;
1658		}
1659	      while (ISSPACE(*++src))
1660		;
1661
1662	      end = src;
1663	      while (*end != '\0' && !ISSPACE(*end) && *end != '>')
1664		++end;
1665
1666	      for (param = tmpl->params, arg = inst->args; param;
1667		   param = param->next, arg = arg->next)
1668		{
1669		  if (end - src == strlen (param->name)
1670		      && !memcmp (src, param->name, end - src))
1671		    {
1672		      src = end;
1673		      break;
1674		    }
1675		}
1676
1677	      if (param == NULL)
1678		fail ("template '%s' has no parameter '%.*s'\n",
1679		      tmpl->name, (int)(end - src), src);
1680
1681	      while (ISSPACE(*src))
1682		++src;
1683	      if (*src != '>')
1684		fail ("%s: %d: missing '>'\n", filename, lineno);
1685
1686	      memcpy(ptr1, arg->val, strlen(arg->val));
1687	      ptr1 += strlen(arg->val);
1688	      ++src;
1689	    }
1690
1691	  *ptr1 = '\0';
1692
1693	  expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
1694			    lineno);
1695
1696	  free (str2);
1697	  free (name2);
1698	}
1699    }
1700
1701  return idx;
1702}
1703
1704static void
1705process_i386_opcodes (FILE *table)
1706{
1707  FILE *fp;
1708  char buf[2048];
1709  unsigned int i, j, nr;
1710  char *str, *p, *last, *name;
1711  htab_t opcode_hash_table;
1712  struct opcode_hash_entry **opcode_array = NULL;
1713  int lineno = 0, marker = 0;
1714
1715  filename = "i386-opc.tbl";
1716  fp = stdin;
1717
1718  i = 0;
1719  opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1720					 opcode_hash_eq, NULL,
1721					 xcalloc, free);
1722
1723  fprintf (table, "\n/* i386 opcode table.  */\n\n");
1724  fprintf (table, "static const insn_template i386_optab[] =\n{\n");
1725
1726  /* Put everything on opcode array.  */
1727  while (!feof (fp))
1728    {
1729      if (fgets (buf, sizeof (buf), fp) == NULL)
1730	break;
1731
1732      p = remove_leading_whitespaces (buf);
1733
1734      for ( ; ; )
1735	{
1736	  lineno++;
1737
1738	  /* Skip comments.  */
1739	  str = strstr (p, "//");
1740	  if (str != NULL)
1741	    {
1742	      str[0] = '\0';
1743	      remove_trailing_whitespaces (p);
1744	      break;
1745	    }
1746
1747	  /* Look for line continuation character.  */
1748	  remove_trailing_whitespaces (p);
1749	  j = strlen (buf);
1750	  if (!j || buf[j - 1] != '+')
1751	    break;
1752	  if (j >= sizeof (buf) - 1)
1753	    fail (_("%s: %d: (continued) line too long\n"), filename, lineno);
1754
1755	  if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL)
1756	    {
1757	      fprintf (stderr, "%s: Line continuation on last line?\n",
1758		       filename);
1759	      break;
1760	    }
1761	}
1762
1763      switch (p[0])
1764	{
1765	case '#':
1766	  if (!strcmp("### MARKER ###", buf))
1767	    marker = 1;
1768	  else
1769	    {
1770	      /* Since we ignore all included files (we only care about their
1771		 #define-s here), we don't need to monitor filenames.  The final
1772		 line number directive is going to refer to the main source file
1773		 again.  */
1774	      char *end;
1775	      unsigned long ln;
1776
1777	      p = remove_leading_whitespaces (p + 1);
1778	      if (!strncmp(p, "line", 4))
1779		p += 4;
1780	      ln = strtoul (p, &end, 10);
1781	      if (ln > 1 && ln < INT_MAX
1782		  && *remove_leading_whitespaces (end) == '"')
1783		lineno = ln - 1;
1784	    }
1785	  /* Ignore comments.  */
1786	case '\0':
1787	  continue;
1788	  break;
1789	case '<':
1790	  parse_template (p, lineno);
1791	  continue;
1792	default:
1793	  if (!marker)
1794	    continue;
1795	  break;
1796	}
1797
1798      last = p + strlen (p);
1799
1800      /* Find name.  */
1801      name = next_field (p, ',', &str, last);
1802
1803      i = expand_templates (name, str, opcode_hash_table, &opcode_array,
1804			    lineno);
1805    }
1806
1807  /* Process opcode array.  */
1808  for (j = 0; j < i; j++)
1809    {
1810      struct opcode_hash_entry *next;
1811
1812      for (next = opcode_array[j]; next; next = next->next)
1813	{
1814	  name = next->name;
1815	  str = next->opcode;
1816	  lineno = next->lineno;
1817	  last = str + strlen (str);
1818	  output_i386_opcode (table, name, str, last, lineno);
1819	}
1820    }
1821
1822  fclose (fp);
1823
1824  fprintf (table, "};\n");
1825
1826  /* Generate opcode sets array.  */
1827  fprintf (table, "\n/* i386 opcode sets table.  */\n\n");
1828  fprintf (table, "static const insn_template *const i386_op_sets[] =\n{\n");
1829  fprintf (table, "  i386_optab,\n");
1830
1831  for (nr = j = 0; j < i; j++)
1832    {
1833      struct opcode_hash_entry *next = opcode_array[j];
1834
1835      do
1836	{
1837	  ++nr;
1838	  next = next->next;
1839	}
1840      while (next);
1841      fprintf (table, "  i386_optab + %u,\n", nr);
1842    }
1843
1844  fprintf (table, "};\n");
1845}
1846
1847static void
1848process_i386_registers (FILE *table)
1849{
1850  FILE *fp;
1851  char buf[2048];
1852  char *str, *p, *last;
1853  char *reg_name, *reg_type, *reg_flags, *reg_num;
1854  char *dw2_32_num, *dw2_64_num;
1855  int lineno = 0;
1856
1857  filename = "i386-reg.tbl";
1858  fp = fopen (filename, "r");
1859  if (fp == NULL)
1860    fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1861	  xstrerror (errno));
1862
1863  fprintf (table, "\n/* i386 register table.  */\n\n");
1864  fprintf (table, "static const reg_entry i386_regtab[] =\n{\n");
1865
1866  while (!feof (fp))
1867    {
1868      if (fgets (buf, sizeof (buf), fp) == NULL)
1869	break;
1870
1871      lineno++;
1872
1873      p = remove_leading_whitespaces (buf);
1874
1875      /* Skip comments.  */
1876      str = strstr (p, "//");
1877      if (str != NULL)
1878	str[0] = '\0';
1879
1880      /* Remove trailing white spaces.  */
1881      remove_trailing_whitespaces (p);
1882
1883      switch (p[0])
1884	{
1885	case '#':
1886	  fprintf (table, "%s\n", p);
1887	case '\0':
1888	  continue;
1889	  break;
1890	default:
1891	  break;
1892	}
1893
1894      last = p + strlen (p);
1895
1896      /* Find reg_name.  */
1897      reg_name = next_field (p, ',', &str, last);
1898
1899      /* Find reg_type.  */
1900      reg_type = next_field (str, ',', &str, last);
1901
1902      /* Find reg_flags.  */
1903      reg_flags = next_field (str, ',', &str, last);
1904
1905      /* Find reg_num.  */
1906      reg_num = next_field (str, ',', &str, last);
1907
1908      fprintf (table, "  { \"%s\",\n    ", reg_name);
1909
1910      process_i386_operand_type (table, reg_type, stage_registers, "\t",
1911				 lineno);
1912
1913      /* Find 32-bit Dwarf2 register number.  */
1914      dw2_32_num = next_field (str, ',', &str, last);
1915
1916      /* Find 64-bit Dwarf2 register number.  */
1917      dw2_64_num = next_field (str, ',', &str, last);
1918
1919      fprintf (table, ",\n    %s, %s, { %s, %s } },\n",
1920	       reg_flags, reg_num, dw2_32_num, dw2_64_num);
1921    }
1922
1923  fclose (fp);
1924
1925  fprintf (table, "};\n");
1926
1927  fprintf (table, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1928}
1929
1930static void
1931process_i386_initializers (void)
1932{
1933  unsigned int i;
1934  FILE *fp = fopen ("i386-init.h", "w");
1935  char *init;
1936
1937  if (fp == NULL)
1938    fail (_("can't create i386-init.h, errno = %s\n"),
1939	  xstrerror (errno));
1940
1941  process_copyright (fp);
1942
1943  for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1944    {
1945      fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1946      init = xstrdup (cpu_flag_init[i].init);
1947      process_i386_cpu_flag (fp, init, 1, "", "  ", -1);
1948      free (init);
1949    }
1950
1951  fprintf (fp, "\n");
1952
1953  fclose (fp);
1954}
1955
1956/* Program options.  */
1957#define OPTION_SRCDIR	200
1958
1959struct option long_options[] =
1960{
1961  {"srcdir",  required_argument, NULL, OPTION_SRCDIR},
1962  {"debug",   no_argument,       NULL, 'd'},
1963  {"version", no_argument,       NULL, 'V'},
1964  {"help",    no_argument,       NULL, 'h'},
1965  {0,         no_argument,       NULL, 0}
1966};
1967
1968static void
1969print_version (void)
1970{
1971  printf ("%s: version 1.0\n", program_name);
1972  xexit (0);
1973}
1974
1975static void
1976usage (FILE * stream, int status)
1977{
1978  fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1979	   program_name);
1980  xexit (status);
1981}
1982
1983int
1984main (int argc, char **argv)
1985{
1986  extern int chdir (char *);
1987  char *srcdir = NULL;
1988  int c;
1989  unsigned int i, cpumax;
1990  FILE *table;
1991
1992  program_name = *argv;
1993  xmalloc_set_program_name (program_name);
1994
1995  while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1996    switch (c)
1997      {
1998      case OPTION_SRCDIR:
1999	srcdir = optarg;
2000	break;
2001      case 'V':
2002      case 'v':
2003	print_version ();
2004	break;
2005      case 'd':
2006	debug = 1;
2007	break;
2008      case 'h':
2009      case '?':
2010	usage (stderr, 0);
2011      default:
2012      case 0:
2013	break;
2014      }
2015
2016  if (optind != argc)
2017    usage (stdout, 1);
2018
2019  if (srcdir != NULL)
2020    if (chdir (srcdir) != 0)
2021      fail (_("unable to change directory to \"%s\", errno = %s\n"),
2022	    srcdir, xstrerror (errno));
2023
2024  /* cpu_flags isn't sorted by position.  */
2025  cpumax = 0;
2026  for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
2027    if (cpu_flags[i].position > cpumax)
2028      cpumax = cpu_flags[i].position;
2029
2030  /* Check the unused bitfield in i386_cpu_flags.  */
2031#ifdef CpuUnused
2032  static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
2033
2034  if ((cpumax - 1) != CpuMax)
2035    fail (_("CpuMax != %d!\n"), cpumax);
2036#else
2037  static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
2038
2039  if (cpumax != CpuMax)
2040    fail (_("CpuMax != %d!\n"), cpumax);
2041
2042  c = CpuNumOfBits - CpuMax - 1;
2043  if (c)
2044    fail (_("%d unused bits in i386_cpu_flags.\n"), c);
2045#endif
2046
2047  static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
2048
2049  /* Check the unused bitfield in i386_operand_type.  */
2050#ifdef OTUnused
2051  static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2052		 == OTNum + 1);
2053#else
2054  static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2055		 == OTNum);
2056
2057  c = OTNumOfBits - OTNum;
2058  if (c)
2059    fail (_("%d unused bits in i386_operand_type.\n"), c);
2060#endif
2061
2062  qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
2063	 compare);
2064
2065  qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
2066	 sizeof (opcode_modifiers [0]), compare);
2067
2068  qsort (operand_types, ARRAY_SIZE (operand_types),
2069	 sizeof (operand_types [0]), compare);
2070
2071  table = fopen ("i386-tbl.h", "w");
2072  if (table == NULL)
2073    fail (_("can't create i386-tbl.h, errno = %s\n"),
2074	  xstrerror (errno));
2075
2076  process_copyright (table);
2077
2078  process_i386_opcodes (table);
2079  process_i386_registers (table);
2080  process_i386_initializers ();
2081
2082  fclose (table);
2083
2084  exit (0);
2085}
2086